Skip to main content
Every error thrown by the SDK is an instance of DeepIDVError or one of its subclasses. No untyped exceptions escape the public API, so you can branch on instanceof and handle each case precisely.

Error hierarchy

All error classes are exported from @deepidv/server:

Error catalog

DeepIDVError (base class)

The base class for all SDK errors. Carries HTTP context when available. Every subclass implements toJSON() for structured logging (see below).

ValidationError — HTTP 400

Thrown on HTTP 400, or before any network call when input fails Zod schema validation. The message names the offending field.

AuthenticationError — HTTP 401

Your API key is invalid, expired, or missing. Carries redactedKey (last 4 characters only) — safe to log.

InsufficientFundsError — HTTP 402

The funds / subscription gate failed — your account doesn’t have enough balance for the requested operation.

AuthorizationError — HTTP 403

The API key is valid but lacks permission for the requested resource.

NotFoundError — HTTP 404

The requested resource doesn’t exist — e.g. an unknown session ID, or an async job that has been pruned by TTL.

RateLimitError — HTTP 429

Thrown after all retries are exhausted. The SDK already retried with exponential backoff, so you’ve hit a sustained rate limit. retryAfter (seconds, from the Retry-After header) tells you how long to wait.

ServiceUnavailableError — HTTP 503

A transient upstream timeout. Some screening methods (pepSanctions, titleCheck) surface this immediately without retrying because the server bounds an un-cancellable upstream — back off and try again later.

NetworkError

A network-level failure: DNS resolution failure, connection refused, socket hangup. status is undefined.

TimeoutError

A single attempt exceeded the configured timeout (API requests) or uploadTimeout (uploads). Consider increasing the relevant timeout in configuration, or retrying.

AdverseMediaFailedError

An adverse-media async job terminated in the failed state. Carries the jobId that failed.

PollTimeoutError

AdverseMediaHandle.wait() exceeded its timeoutMs budget before the job completed. This does not mean the job died — it may still complete server-side. Carries timeoutMs and jobId; resume by polling client.asyncJobs.get(jobId).

Retry semantics

The SDK retries only transient failures — HTTP 429 and 5xx — up to maxRetries times (default 3) with exponential backoff and jitter. It never retries 4xx client errors, since those are caller bugs a retry won’t fix. By the time a RateLimitError reaches your catch block, the retries are already spent. See Configuration → retry & timeout behavior for tuning, and note that screening.pepSanctions / screening.titleCheck deliberately opt out of retries.

Error decision tree

Structured logging with toJSON()

Every DeepIDVError implements toJSON(), so JSON.stringify() produces a clean, log-safe object. The full API key is never serialized:
This makes it safe to forward errors directly to Sentry, Datadog, or any error-tracking service.

Error.cause chaining

All SDK errors preserve the original cause via the standard Error.cause property — useful for debugging the exact failure at each layer: