Errors
Every error the SDK throws extends DinioError. Calls never resolve to null or undefined
in place of an error.
| Class | When |
|---|---|
DinioApiError |
The API refused the request. Has status, code, message, details. |
DinioInputError |
The SDK rejected an argument before sending anything. |
DinioNotFoundError |
A by-name function found nothing; the message lists what exists. |
DinioNetworkError |
The API could not be reached (DNS, TLS, offline). The original error is its cause. |
DinioTimeoutError |
No full response within timeoutMs. |
DinioAbortError |
Your AbortSignal aborted the call. |
DinioDecodeError |
The response was not the API’s — e.g. a proxy error page. Has status, bodySnippet. |
API errors
Section titled “API errors”DinioApiError.code is the API’s error.code: NOT_FOUND,
CONFLICT, MANAGED_RECORD, MANAGED_CERTIFICATE, VALIDATION, FORBIDDEN, SUSPENDED,
UNAUTHENTICATED, INVALID_API_KEY, INVALID_TOKEN, BAD_REQUEST, PAYLOAD_TOO_LARGE,
IMPORT_FAILED, DISCOVERY_FAILED, AUDIT_DISABLED, TELEMETRY_DISABLED,
NO_SUBSCRIPTION, PLAN_LIMIT, PLAN_NOT_AVAILABLE, PLAN_DOWNGRADE_BLOCKED, LIST_LIMIT,
IMPORT_RUNNING, IMPORT_INTERRUPTED, FETCH_FAILED, SOURCE_MANAGED, INTERNAL, or a
newer code as a plain string. details carries the violated rules on 409 and 422.
import { DinioApiError } from '@dinio/sdk';
try { await dinio.zones.create('example.com');} catch (err) { if (err instanceof DinioApiError && err.code === 'CONFLICT') { // the zone already exists } else { throw err; }}try { await dinio.records.create({ zone_id, name: 'www.example.com', type: 'CNAME', data: 'example.net' });} catch (err) { if (err instanceof DinioApiError && err.status === 409) { console.error(err.message, err.details); // every violated zone rule } throw err;}For MANAGED_RECORD and MANAGED_CERTIFICATE, details is a ManagedDetails
({ managed_by, name }): what keeps the resource, and the redirect’s name.
import { DinioApiError, type ManagedDetails } from '@dinio/sdk';
try { await dinio.records.delete(valueId);} catch (err) { if (err instanceof DinioApiError && err.code === 'MANAGED_RECORD') { const { managed_by, name } = err.details as ManagedDetails; console.error(`kept by ${managed_by} for ${name} — delete the redirect instead`); } else { throw err; }}For IMPORT_FAILED, importReport(err) returns the import report — what was refused, by
line or entry — and undefined for any other error:
import { importReport } from '@dinio/sdk';
try { await dinio.zones.import('example.com', 'bind', zoneFile);} catch (err) { const report = importReport(err); if (!report) throw err; for (const issue of report.records.errors) console.error(`line ${issue.ref}: ${issue.message}`);}For the package errors, planLimit(err) returns { key, limit, used?, requested? } of a PLAN_LIMIT, and subscriptionLine(err) the line ('auth' or 'filter')
of a NO_SUBSCRIPTION; both return undefined for any other error:
import { planLimit, subscriptionLine } from '@dinio/sdk';
try { await dinio.clientIdentities.create({ id_type: 'Path', name: 'tablet' });} catch (err) { const limit = planLimit(err); const line = subscriptionLine(err); if (limit) console.error(`${limit.key}: ${limit.used ?? limit.requested} of ${limit.limit}`); else if (line) console.error(`choose a ${line} package first`); else throw err;}instanceof works for every class. Each error also has a name ("DinioApiError", …), for
the rare case of two copies of the package in one bundle.