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. |
Details
Section titled “Details”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 records and certificates
Section titled “Managed records and certificates”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.
In the CLI and SDKs
Section titled “In the CLI and SDKs”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
DinioApiErrorwithstatus,code,message,details; see Errors. - Rust — returns
Error::Api(ApiError { status, code, message, details }); see Errors.