Skip to content

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 kid after that key was destroyed.
  • Importing a keystore whose alias maps to the kid of 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}/keys on the Admin API answers this 409 with the same type, title and detail as the key plane behind it, so you can branch on type on 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 failures with reason KEY_ID_RETIRED, and every other entry is imported.

How to Resolve

  1. Choose a Key ID this tenant has never used and submit the request again.
  2. 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.
  3. 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); every kid in that list is retired.
  4. 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.