Bootstrap Tenant Uses Deployment Custody
URI: https://docs.ankatech.co/errors/bootstrap-tenant-deployment-custody
HTTP Status: 422 Unprocessable Entity
When you see this
A per-tenant key-backend write named a bootstrap tenant other than the platform tenant as its target. The bootstrap tenants are the two tenants every deployment is created with: the platform tenant (00000000-0000-0000-0000-000000000001) and the first business tenant (00000000-0000-0000-0000-000000000002). Their key-encryption keys are created on the deployment's own key-protection backend when the backend is activated, and the platform reads the deployment as bound only while each of them holds that key. A bootstrap tenant therefore cannot take a per-tenant Edition or bring its own key-material backend.
The refusal covers every write that could move such a tenant's keys:
- assigning or clearing a per-tenant Edition (
PUTandDELETE /api/v3/admin/platform/tenants/{tenantId}/key-backend/edition); - declaring, binding, rotating the credential of, or reverting a BYOK backend, on the platform plane (
/api/v3/admin/platform/tenants/{tenantId}/key-backend/byok) and on the tenant plane (/api/v3/admin/tenants/{tenantId}/key-backend/byok), including the driver-form declaration (PUT .../key-backend/byok/driver-declaration).
The check is the first act of each of these operations. A body that fails request validation (a missing or malformed member) is still answered 400 first, before the operation runs; a body that passes it but that the operation's own descriptor, admission or typed checks would refuse gets this 422 instead, because the target is judged before any of those checks. A refused call reads no tenant row, contacts no key backend and moves no key. Its one write is a FAILURE audit row filed under the tenant named, carrying the refused operation as <operation>-refused (for example assign-refused or declare-refused) and the reason BOOTSTRAP_TENANT_DEPLOYMENT_CUSTODY. The platform tenant itself is answered first with Invalid Tenant Custody Scope; this type answers every other bootstrap tenant.
Reading the Edition view of the first business tenant (GET .../key-backend/edition) is not refused: it reports the deployment backend the tenant inherits. Its BYOK status reports allowsTenantOverride: false, so a client never offers it a change the platform refuses.
Common Causes
- Assigning an Edition to the first business tenant to try a managed tier.
- Declaring a BYOK backend on the first business tenant from its own tenant administrator session.
- A client that iterates every tenant and applies the same Edition or BYOK change to all of them.
Response Example
{
"type": "https://docs.ankatech.co/errors/bootstrap-tenant-deployment-custody",
"title": "Bootstrap Tenant Uses Deployment Custody",
"status": 422,
"detail": "A bootstrap tenant's keys are held by the deployment's key-protection backend; it cannot take a per-tenant Edition or bring its own key-material backend",
"instance": "/api/v3/admin/platform/tenants/00000000-0000-0000-0000-000000000002/key-backend/edition",
"timestamp": 1730000000,
"extensions": {
"requestId": "3f2b8c1e-6d4a-4e9b-9a57-0c8d1e2f3a4b"
}
}
Content-Type: application/problem+json — the response follows RFC 9457 Problem Details.
How to Resolve
- Apply the Edition or the BYOK backend to a tenant you created, not to a bootstrap tenant. A tenant that needs its own backend or a managed tier is provisioned as its own tenant.
- To change the backend that protects the bootstrap tenants, change the deployment's own key-protection backend through
/api/v3/admin/platform/setup/*; the bootstrap tenants follow it. - In a client that applies a change to every tenant, skip the two bootstrap tenant ids. The detail is fixed and names no tenant, Edition or backend, so retrying with the same target always gets the same answer.
For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.