Skip to content

Errors

An error always comes in the response envelope with success: false:

{
"success": false,
"error": { "code": "NOT_FOUND", "message": "Zone not found" }
}

Branch on error.code, not on message — messages are for people and may change.

Status error.code When
400 BAD_REQUEST The body is not valid JSON.
401 UNAUTHENTICATED No Authorization header.
401 INVALID_API_KEY The key is unknown or revoked, or its user is suspended.
401 INVALID_TOKEN The bearer token has no du_/dz_ prefix, so it is not an API key.
403 FORBIDDEN The key is valid but may not do this — e.g. a zone key outside its zone or on a DNS filtering route, or an Administrator deleting a zone.
403 SUSPENDED The zone or client identity is suspended: it can be read and deleted, not changed.
403 NO_SUBSCRIPTION You have no package in that line (auth or filter), so nothing can be added there. details.line says which.
403 PLAN_LIMIT The package doesn’t allow this: one more zone, lease, health check, client, list or rule, a shorter health-check interval, or older statistics.
404 NOT_FOUND The resource does not exist, or the route is unknown.
409 CONFLICT The change conflicts with existing data: a duplicate name, a record that breaks a zone rule, a redirect name the zone does not serve, a resource still referenced by others, or a zone discovery already running.
409 MANAGED_RECORD The record value is kept by Dinio for a redirect or a certificate issuance, or a redirect holds the name you tried to add an A/AAAA/CNAME at.
409 MANAGED_CERTIFICATE The certificate was issued automatically for a redirect; change the redirect’s tls instead.
409 PLAN_NOT_AVAILABLE The package can’t be chosen: unknown, or not for self-service.
409 PLAN_DOWNGRADE_BLOCKED You use more than the chosen package allows; details.violations lists what. Nothing changed.
409 SOURCE_MANAGED The sinkhole list is filled from a URL: it takes no manual rules or imports. details.url is the source.
409 IMPORT_RUNNING An import into this sinkhole list is already running.
413 PAYLOAD_TOO_LARGE A zone file over 2 MiB, or a sinkhole list import over 10 MiB.
422 VALIDATION The request is malformed: a missing or unknown field, a bad uuid, an unknown enum label, invalid record data.
422 IMPORT_FAILED A zone import refused records; nothing was written, and details holds the report.
422 DISCOVERY_FAILED Discovery found no nameserver to ask.
422 LIST_LIMIT A sinkhole list would have more than 500 000 rules or 1 000 Regex rules, whatever the package.
422 FETCH_FAILED A sinkhole list’s source URL could not be downloaded; message says why.
500 INTERNAL Unexpected server error. Safe to retry later.
503 AUDIT_DISABLED, TELEMETRY_DISABLED The audit log or statistics are not available right now.
503 IMPORT_INTERRUPTED A sinkhole list import was only partly written. Repeat it.

422 and 409 usually carry details with every problem found, so one round trip shows everything that is wrong.

For a field-level validation error, details lists the issues per field:

{
"success": false,
"error": {
"code": "VALIDATION",
"message": "interval: timeout × (retries + 1) + retry_interval × retries = 75 s must be smaller than interval (60 s)",
"details": [{ "path": ["interval"], "message": "timeout × (retries + 1) + retry_interval × retries = 75 s must be smaller than interval (60 s)" }]
}
}

For a record that breaks a zone rule, details lists the violated rules:

{
"success": false,
"error": {
"code": "CONFLICT",
"message": "CNAME must be the only record at www.example.com, found A 192.0.2.1 (RFC 1034 §3.6.2, RFC 2181 §10.1)",
"details": [
"CNAME must be the only record at www.example.com, found A 192.0.2.1 (RFC 1034 §3.6.2, RFC 2181 §10.1)"
]
}
}

MANAGED_RECORD and MANAGED_CERTIFICATE say what keeps the resource and for which name, so you can point the user at the right place:

{
"success": false,
"error": {
"code": "MANAGED_RECORD",
"message": "CNAME go.example.com is managed by its redirect — change or delete the redirect instead",
"details": { "managed_by": "Redirect", "name": "go.example.com" }
}
}

managed_by is Redirect or Acme; see Records Dinio keeps.

The CLI and the SDKs keep code, message and details intact:

  • CLI — prints the message and details, and exits with a code per error class; see Output and exit codes.
  • TypeScript — throws DinioApiError with status, code, message, details; see Errors.
  • Rust — returns Error::Api(ApiError { status, code, message, details }); see Errors.