Errors and troubleshooting¶
How to read DKS public API errors, what failure_message means, and what to do in common situations.
Who can do this: anyone calling the API or using the console. Mutations still require super_admin.
Error body shape¶
Most 4xx/5xx responses look like:
detail is a string for handler-raised errors.
422 validation uses an array:
{
"detail": [
{
"loc": ["body", "name"],
"msg": "String should match pattern …",
"type": "string_pattern_mismatch"
}
]
}
Every route and response schema is in the API reference.
HTTP status codes (public API)¶
These are the codes /v1/public/clusters… and /v1/catalog return.
400 Bad Request¶
Typical detail | What to do |
|---|---|
Unknown machine tier: size is not a known machine tier (available machine tiers: …) | Use a tier id from the catalog (dks.c5.xlarge, not an internal size name). |
| Unknown Kubernetes version | Use a kubernetes_versions[].id from the catalog (Abidjan: v1.32.4). |
unknown zone='…' | Use abidjan (or another zone the catalog documents). |
Idempotency-Key must match '^[A-Za-z0-9_\\-:.]{8,255}$' | Key 8–255 characters: letters, digits, _, -, :, .. |
no organization specified and user has no preferred organization | Send X-Door-Organization or ?organization= or set a preferred org on your Door account. |
| Empty node pools / other create validation | Send at least one pool; see limits. |
Exposure cannot change (not Provisioned, deleting, public disabled, invalid mode) | Wait until Provisioned, or use private/public only. |
| Firewall protocol / port / CIDR | Fix the rule; IPv4 only, ≤16 CIDRs. |
| Invalid node name on delete | Node name must look like a DNS hostname (see Nodes tab / kubectl get nodes). |
401 Unauthorized¶
detail | What to do |
|---|---|
Authorization header missing | Send Authorization: Bearer $DOOR_TOKEN. |
Authorization scheme must be Bearer | Use Bearer, not another scheme. |
Bearer token is empty | Non-empty token. |
invalid bearer token | Sign in again; tokens expire. See Authentication. |
402 Payment Required¶
Prepaid organizations only (enterprise invoice orgs skip this gate).
detail | What to do |
|---|---|
Your organization does not have enough credit balance to cover remaining cluster costs plus one month for the new cluster. Please top up your credits to create a cluster. | Top up, or contact your Door account team, then retry create. |
Your organization does not have enough credit balance to cover remaining cluster costs after this scale. Please top up your credits. | Same, before adding or scaling pools. |
403 Forbidden¶
You are authenticated but not allowed.
| Typical case | What to do |
|---|---|
member on a mutation | Ask a super_admin. |
| Not a member of the cluster's organization | Switch organization or request access. |
user … has no super_admin role on any organization | Pre-check on some writes; you need super_admin somewhere, then on this org. |
List/get as member is allowed. Kubeconfig download is allowed for member unless your operator has tightened that setting.
404 Not Found¶
Typical detail | What to do |
|---|---|
cluster {id} not found | Wrong id, or the cluster is fully gone after delete. Treat 404 after delete as success. |
| Organization not found | Check the org name/id. |
| Elastic IP / firewall rule / node pool not found | Refresh the list. After EIP release, 404 on GET is success. |
no projected state for cluster {id} | /state has nothing yet; retry shortly after create. |
A cluster that exists in another organization typically returns 403, not 404. The list endpoint is org-scoped and will not show it.
409 Conflict¶
| Typical case | What to do |
|---|---|
| Cluster name already exists | Pick another name (names are immutable). |
Idempotency-Key '…' was previously used with a different payload | New key, or replay the same body. |
Cluster not Provisioned (pools, EIP, firewall, node list: cluster not ready yet or phase message) | Wait for Provisioned. |
| Exposure: previous change still being applied | Retry the same PATCH shortly. |
| Node-pool op already in flight; last pool; duplicate pool name | Wait, or keep at least one pool. |
EIP name taken; EIP not Ready/Failed on delete; exposure vs network_mode mismatch | Fix name, wait, or create the cluster with the matching network mode. |
| Firewall duplicate name | Another name. |
| Delete: cluster still has Door hub environments | Delete those environments, or DELETE …?force=true. |
| PATCH metadata on a cluster already deleting | Stop; the cluster is going away. |
Kubeconfig while not ControlPlaneReady or Provisioned | Wait. Message may still say "only available when phase=Provisioned". |
422 Unprocessable Content¶
Schema or merged pool bounds: extra fields (extra="forbid"), missing required fields, count/auto_scale/min_nodes/max_nodes combination, empty PATCH (at least one of: tags, description or pool fields), count=0 without autoscaling.
Note
The public cluster and catalog routes do not return 429 Too Many Requests. There is no rate-limit code for your client to handle.
502 Bad Gateway¶
Auth or Door hub checks failed (for example hub environments could not be torn down on ?force=true). Retry shortly. If it persists, contact Door support with the cluster id.
503 Service Unavailable¶
| Typical case | What to do |
|---|---|
| Zone cannot accept the create (capacity) | Retry later or contact your account team. |
| Elastic IP product / public pool disabled or exhausted | Use private on an intranet cluster, or contact your account team. |
| Node inventory temporarily unavailable | Retry GET nodes. |
| Kubeconfig download not configured / server URL not ready | Retry; if exposure is public, wait until public_exposure_fqdn is set. |
| Delete: cannot verify Door hub environments | Retry without assuming the cluster was deleted. |
| Catalog missing for the cluster's zone | Contact Door support (platform misconfiguration). |
500 Internal Server Error¶
Unexpected server failure (including a kubeconfig that cannot be decrypted or rewritten). Retry once, then contact support with the cluster id. Do not send tokens.
failure_message on a Failed cluster¶
When phase is Failed (or a delete is stuck with a failure), failure_message is server-authored customer copy. It is never raw platform text.
| Message | What to do |
|---|---|
We couldn't set up networking for this cluster in this zone. Our team has been notified — please retry or contact support. | Retry create, or delete and recreate. If it repeats, contact support with the cluster id. |
Setup timed out waiting for the cluster to become healthy. You can retry, or delete and recreate. | Delete and recreate, or contact support. |
Network routing didn't finish setting up. Support can help recover this cluster. | Contact Door support with the cluster id. Do not keep retrying the same broken row without them. |
Something went wrong during setup (ref {cluster_id}). Contact support if this persists. | Give Door support that cluster id. This is the generic message for any other failure. |
progress.title is Setup failed. progress.message matches failure_message.
Common situations¶
Cluster stays in Provisioning¶
Follow GET …/state or the console Provisioning page. Copy comes from progress.title / progress.message. There is no published maximum duration in the API. Stay on the progress view until Provisioned or Failed. If progress does not move for a long time, contact Door support with the cluster id. Do not issue overlapping creates with the same name.
Kubeconfig returns 202 in a loop¶
202 means a fetch was queued. Response includes retry_after_seconds (platform default 5) and header Retry-After. Call the same GET again after that delay. Need ControlPlaneReady or Provisioned (409 otherwise). If 202 continues for many minutes after Provisioned, contact support with the cluster id.
kubectl times out on a private cluster¶
exposure_mode=private means the API is not on the Internet. Connect from your private network or VPN, use the kubeconfig downloaded after the cluster is private (server: is private_api_server_endpoint, port 6443). If you expected the Internet hostname, switch to public exposure and download kubeconfig again (server: is https://<fqdn> on 443).
Node count lower than desired¶
Desired size is node_pools[].count (or autoscaler bounds). Listed workers come from a snapshot that can be empty (cold) or briefly behind (stale). Wait until Provisioned, refresh the Nodes tab, and check ready. Autoscaling may sit at min_nodes. Failed nodes show status: Failed. If desired count stays higher than Ready workers after the pool operation has finished, contact support with the cluster id.
Delete takes a long time¶
202 then phase=Deleting. Progress message: Removing your cluster's resources. This can take a few minutes. Default list hides deleting rows; use include_deleted=true. Success is Deleted then 404. Hub environments block delete with 409 until you remove them or pass force=true.
Exposure PATCH 400 vs 409¶
Not Provisioned → 400. Another change still applying → 409, retry.
Contact Door support¶
Use your Door account team / Door support channel (no public ticket URL is published in this API). Always include:
- Cluster id (UUID), not only the name
- Organization slug (
acme) - Zone (
abidjan) - Approximate time and the
failure_messageor HTTPdetail(never the Bearer token)
The generic setup failure sentence already embeds ref {cluster_id} so support can find the cluster.