Declared Backend Cannot Be Changed In Place
URI: https://docs.ankatech.co/errors/deployment-backend-token-change-refused
HTTP Status: 422 Unprocessable Entity
When you see this
PUT /api/v3/admin/platform/setup/backend/configuration was submitted with a backend token different from the one the deployment already declares. The declared backend cannot be changed by re-configuring coordinates, so the request is refused before anything is written.
The reason is custody, not policy. The deployment holds one sealed key-protection credential, at one fixed reference, and that envelope belongs to the backend currently declared — the reference is deliberately not per-token. Re-pointing the declaration in place would leave a credential for the old backend sitting under a descriptor naming the new one, and the next credential write would then be asked to prove that the new backend's credential reaches the same key-encryption key as a credential that never touched it. That proof cannot pass, and it should not be made to.
So the platform makes the state unreachable rather than repairing it afterwards. To move to a different backend, withdraw the declaration first.
This refusal is independent of whether the deployment is bound. A bound deployment is refused 409 Key Protection Backend Already Bound by the immutability gate; an unbound one is refused 422 here. Neither one re-points the declaration.
Common Causes
- An operator edited the backend selector on the setup screen and submitted the coordinate form, expecting the declaration to follow the selection.
- A first activation failed and the operator went back to the coordinate form to point the same deployment at a different cloud provider.
- A script re-ran the console chain with a new token but without the withdrawal link in front of it.
Response Example
{
"type": "https://docs.ankatech.co/errors/deployment-backend-token-change-refused",
"title": "Declared backend cannot be changed in place",
"status": 422,
"detail": "The deployment already declares 'gcp-kms'. The declared backend cannot be changed by re-configuring coordinates, because the sealed credential belongs to the backend currently declared. Withdraw the declaration first (DELETE /api/v3/admin/platform/setup/backend/declare), then declare 'aws-kms'.",
"instance": "/api/v3/admin/platform/setup/backend/configuration",
"timestamp": 1730000000,
"extensions": {
"requestId": "b41c8e7a-5d92-4f16-9a03-7e2c6b8d4051"
}
}
Content-Type: application/problem+json — the response follows RFC 9457 Problem Details.
The detail names both tokens and the route out, and no coordinate: a declared token is registry vocabulary, while a key ARN, a Cloud KMS resource path or an Azure account URL is deployment topology.
Nothing was destroyed on the way to this refusal. It is evaluated before the descriptor row is loaded and before any write: the descriptor still carries the original token and its coordinates, the sealed credential is still present and untouched, and no cache eviction of any kind was published.
How to Resolve
- Confirm what the deployment declares today with
GET /api/v3/admin/platform/setup/backend/configuration. - If you only meant to correct the coordinates of the backend already declared, resubmit with the
backendmember unchanged. A same-token coordinate edit is the ordinary write it has always been and is not refused here. - If you genuinely want a different backend, withdraw the declaration:
DELETE /api/v3/admin/platform/setup/backend/declare. In the console this is the withdrawal action on the Cryptography & Trust → HSM / Cloud KMS screen. - Then run the chain again from the top: declare the new token, save its coordinates, seal its credential and activate.
What the withdrawal costs you
The withdrawal disposes the sealed credential, its retained predecessor and any transient candidate, because a sealed value may not outlive the descriptor that owns it. There is no restore point across the change: restorePrevious afterwards answers 422 Deployment Backend Restore Unavailable.
So moving A → B and back to A costs a re-seal of A's credential each way. Have the credential you intend to use to hand before you withdraw. The withdrawal also clears the bootstrap key-encryption-key rows the platform created, and its audit row names every key reference it stopped tracking on your cloud account so you can delete those keys yourself.
The window closes at the bind
Withdrawal is available only while the deployment is not yet bound — that is, while at least one bootstrap tenant lacks an active key-encryption key. Once both hold one, the withdrawal answers 409 for the same reason every other re-pointing path does.
For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.