Skip to content

Key-State Seal Key Closure

URI: https://docs.ankatech.co/errors/key-state-seal-key-closure
HTTP Status: 409 Conflict

When you see this

The request does not fit how the key-state seal key is closed. Admin API proves the seal key it holds against the generation's stored record every few minutes. When the two do not match, the generation is closed by a mismatch, and only two actions may follow: a compromise rotation, or a reopening after investigation. Nothing was changed.

extensions.reason names the case:

extensions.reason Returned by Meaning
MISMATCH_REQUIRES_COMPROMISE_ROTATION POST /api/v3/admin/platform/key-state-seal-keys/rotations (rotateKeyStateSealKey) with "compromise": false The active generation is closed by a mismatch, so an ordinary rotation is refused
NOT_CLOSED_BY_MISMATCH POST /api/v3/admin/platform/key-state-seal-keys/{generation}/reopen (reopenKeyStateSealKey) The generation is open, or it was closed by backend refusals, so there is nothing to reopen

A generation closed by backend refusals reopens by itself at the next successful proof, once the deployment KEK unwraps it again. It is never reopened by hand.

Common Causes

  • An ordinary rotation was started after a mismatch closed the active generation.
  • A reopening named a generation whose proofClosedBy is not MISMATCH.

Response Example

{
  "type": "https://docs.ankatech.co/errors/key-state-seal-key-closure",
  "title": "Key-State Seal Key Closure",
  "status": 409,
  "detail": "This key-state seal key generation is not closed by a mismatch, so there is nothing to reopen. Nothing was changed.",
  "instance": "/api/v3/admin/platform/key-state-seal-keys/2/reopen",
  "extensions": {
    "reason": "NOT_CLOSED_BY_MISMATCH",
    "requestId": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
  }
}

Content-Type: application/problem+json — the response follows RFC 9457 Problem Details. This is an Admin API body, so the correlation identifier is extensions.requestId; see Error Index & Overview.

How to Resolve

  1. Read listKeyStateSealKeys (GET /api/v3/admin/platform/key-state-seal-keys) and check the generation's proofClosedAt and proofClosedBy.
  2. For MISMATCH_REQUIRES_COMPROMISE_ROTATION, investigate the mismatch first: tampering, a deployment KEK that unwraps to different bytes, or a corrupted process. Then either start the rotation again with "compromise": true, which re-seals every row on its signed state-version floor without trusting either copy of the closed key (the floor signs a row's version, not its content), or reopen the generation with reopenKeyStateSealKey once the investigation showed the stored record is sound.
  3. For NOT_CLOSED_BY_MISMATCH, there is nothing to do: a generation closed by backend refusals reopens once the deployment credential can unwrap it again.

For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.