Material Version Moved
URI: https://docs.ankatech.co/errors/material-version-moved
HTTP Status: 409 Conflict
When you see this
A key rotation names the material version it advances from: the key's PRIMARY version when the rotation was first requested. When the platform's key service locked the key to rotate it, the key was at another version, so the rotation was refused. Nothing was changed: no material was written and no version advanced.
Returned by POST /api/v3/admin/tenants/{tenantId}/keys/{kid}/rotations (rotateKey), where it is one of the 409 answers and owns its type; it is relayed verbatim from the key service. Two cases reach it:
- another rotation of the same key, requested separately, advanced it after your request read the key and before your rotation was applied. Rotations of one key are applied one at a time, so the second one sees the first one's version;
- under a reused
Idempotency-Key, the rotation reserved for that key was never applied, and a different rotation advanced the key in the meantime. The resend repeats the first request's expected version, never a fresh read, so it is refused rather than applied on top of the other rotation.
A resend of a rotation that was applied is never refused for its version: it is answered 200 with the applied rotation and Idempotent-Replayed: true, because the version check belongs to the first execution.
Common Causes
- Two operators, or an operator and a compliance remediation run, rotated the same key at about the same time.
- A client resent a rotation under its original
Idempotency-Keyafter another rotation of the key had landed.
Response Example
{
"type": "https://docs.ankatech.co/errors/material-version-moved",
"title": "Material Version Moved",
"status": 409,
"detail": "Rotation refused: key 'payments-signing-key' is at material version 4, not the expected version 3. Nothing was changed.",
"instance": "/api/v3/admin/tenants/6f1b2c4e-8a3d-4f7e-9c21-5b0d7e9a1f34/keys/payments-signing-key/rotations",
"extensions": {
"requestId": "8b3f0c27-4e1d-4a9b-b6c5-3e7a1d9f2c04"
}
}
Content-Type: application/problem+json — the response follows RFC 9457 Problem Details. The detail names your own key and both versions; branch on type, never on the wording of detail.
How to Resolve
- Read the key (
GET /api/v3/admin/tenants/{tenantId}/keys/{kid}) and check its current material version and algorithm. The rotation you wanted may already be in place. - If a rotation is still wanted, send it as a new rotation under a new
Idempotency-Key. Resending the sameIdempotency-Keyrepeats the same refusal.
A compliance remediation step that receives this refusal records the key as SKIPPED_ALREADY_DONE, the same outcome as a key its own check found already moved.
Related Errors
- Concurrent Modification (409) - another writer held the key longer than the rotation's lock-wait bound, or changed the key's alias record
- Conflict (409) - the PRIMARY material the rotation validated changed while it ran
- Rotation Outcome Unknown (504) - the rotation was sent and no answer arrived
For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.