Capability Grant Overlap
URI: https://docs.ankatech.co/errors/capability-grant-overlap
HTTP Status: 409 Conflict
When you see this
You asked for a Capability Grant and the actor already holds a live grant that overlaps it. Two grants of one actor overlap when their capabilities intersect and their resources intersect. The refusal does not depend on the Exchange Context, the Constraint Policy or the owner of either grant: an actor's live grants never overlap anywhere in the tenant, so every request the actor makes is authorized by at most one grant. Nothing was written.
The operations that create a grant all answer it the same way:
createCapabilityGrant(POST /api/v3/admin/tenants/{tenantId}/capability-grants), a standalone grant;createExchangeGrant(POST /api/v3/admin/exchanges/{id}/grants), a grant owned by a Cryptographic Exchange;createInternalCryptoUseCase, whose grants are written through the same path.
How resources intersect:
- Basic capabilities (
ENCRYPT,DECRYPT,SIGN,VERIFY) intersect on a Key ID both grants name. A wildcard grant (allowWildcardAsset: true) covers every Key ID, so it intersects every basic grant of the actor whose capabilities intersect its own, and every other wildcard grant. - Transformation capabilities (
REENCRYPT,RESIGN) intersect on an ordered key pair both grants name.REENCRYPTfromK1toK2overlaps a secondREENCRYPTfromK1toK2, but notREENCRYPTfromK2toK1, norREENCRYPTfromK1toK1: each pair authorizes its own direction only. - Disjoint capabilities never overlap. An
ENCRYPTgrant and aDECRYPTgrant on the same key are both admitted.
A grant stops counting once it is no longer live: revoked, consumed, retired with its Exchange or with its Exchange Context.
This is a distinct 409 from Concurrent Modification, which means a stale optimistic-lock version, and a retry after a re-read succeeds. An overlap is refused for the same reason on every retry until a conflicting grant ends or the request is narrowed. A client branches on the type member, never on detail.
Common Causes
- Adding a grant to a second Exchange for an actor that already holds the same capability on the same key through another Exchange or a standalone grant, in this or another Exchange Context.
- Creating a kid-named grant for an actor that holds a wildcard grant with an intersecting capability, or a wildcard grant for an actor that holds any intersecting grant.
- Re-running a provisioning script that created the grant on its first run.
Response Example
{
"type": "https://docs.ankatech.co/errors/capability-grant-overlap",
"title": "Capability Grant Overlap",
"status": 409,
"detail": "The actor already holds a live Capability Grant whose capabilities and resources intersect this one, in this or another Exchange Context. Revoke the conflicting grant, or narrow the capabilities or keys of this one.",
"instance": "/api/v3/admin/tenants/7c9e6679-7425-40de-944b-e07fc1f90ae7/capability-grants",
"timestamp": 1730000000,
"extensions": {
"conflictingGrantIds": ["22222222-2222-4222-8222-222222222222"],
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
Content-Type: application/problem+json, following RFC 9457 Problem Details. extensions.conflictingGrantIds lists every live grant the request overlaps. They are grants of the actor you named, in your own tenant. The detail is a fixed sentence: it never repeats the capabilities or Key IDs you submitted.
How to Resolve
- Do not retry unchanged. Every retry is refused for the same reason.
- Read each grant in
extensions.conflictingGrantIds(getCapabilityGrant). If one of them already authorizes what you need, use it. A provisioning script can treat this refusal as "already done" when the conflicting grant is the one it meant to create. - If the existing grant must be replaced, end it first. Revoke an Exchange's grant with
revokeExchangeGrant(or revoke the Exchange), and revoke a standalone grant withrevokeCapabilityGrant. Then repeat the request. - Otherwise narrow the request: drop the intersecting capability, name another key, or name another ordered pair.
- To change only the limits a grant enforces, do not create a second grant: re-pin the existing one to another Constraint Policy version with
replaceCapabilityGrantPolicyVersion.
For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.