Key ID Retired
URI: https://docs.ankatech.co/errors/key-id-retired
HTTP Status: 409 Conflict
When you see this
You tried to create or import a key under a key identifier (kid) that belonged to a key this tenant has destroyed. A Key ID is never reused within its tenant: once every material of a key is destroyed, its identifier is retired for good, and no later key can take it.
This is a different condition from duplicate-kid. duplicate-kid means a key that still exists holds the identifier; key-id-retired means the key is gone and the identifier went with it. Both are 409; branch on the type.
Why a retired Key ID is never reused
The kid travels in the JOSE header of every artefact a key produced, beside the material version ank_kv, which starts at 1 for every new key. If a new key could take a destroyed key's identifier, an old artefact and a new one could both carry the same (kid, ank_kv) pair while referring to unrelated key material. Audit records name keys by the same identifier, so a reused identifier would also merge two keys' histories. Retiring the identifier keeps every kid naming exactly one key for the life of the tenant.
Common Causes
- Re-running a provisioning script that recreates a key with the same
kidafter that key was destroyed. - Importing a keystore whose alias maps to the
kidof a destroyed key. - Destroying a key in order to "free" its identifier, then re-creating it under the same name.
Response Example
{
"type": "https://docs.ankatech.co/errors/key-id-retired",
"title": "Key ID Retired",
"status": 409,
"detail": "The Key ID \"payments-signing-key\" belonged to a destroyed key of this tenant and is never reused. Choose another Key ID.",
"instance": "/api/v3/key-management/keys",
"correlationId": "550e8400-e29b-41d4-a716-446655440000"
}
Content-Type: application/problem+json — the response follows RFC 9457 Problem Details.
The detail names the identifier you submitted and states that it is retired. It states nothing further: not when the key was destroyed, not its algorithm, not its material.
Which routes answer with this type
- Key creation —
POST /api/v3/admin/tenants/{tenantId}/keyson the Admin API answers this409with the sametype,titleanddetailas the key plane behind it, so you can branch ontypeon either plane. - Single-key import — the same refusal, before any material is written.
- Keystore import — the import does not fail as a whole. The entry whose alias maps to a retired Key ID is reported among the response's
failureswith reasonKEY_ID_RETIRED, and every other entry is imported.
How to Resolve
- Choose a Key ID this tenant has never used and submit the request again.
- If the new key replaces the destroyed one in your application, update the application's configuration to the new Key ID. Artefacts the destroyed key protected cannot be recovered under any identifier.
- To check whether an identifier is retired before you use it, list the tenant's deleted keys (
GET /api/v3/key-management/keys?status=deleted_logical); everykidin that list is retired. - To keep an identifier stable across key material changes, rotate the key instead of destroying it: a rotation adds a new material version under the identifier you already have.
For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.