Skip to main content

Error handling

Every failure throws a typed EkycError carrying the HTTP status and the parsed API error envelope:

import { EkycError } from '@drukverify/ekyc-sdk-js';

try {
await client.fraud.detect(image);
} catch (e) {
if (e instanceof EkycError) {
console.log(e.status); // e.g. 400
const err = (e.body as any)?.error;
console.log(err?.type); // stable machine-readable code
console.log(err?.message); // human-readable detail
console.log(err?.request_id); // quote this to support
console.log(err?.doc_url); // documentation for this error
}
}

The API's error contract is { error: { type, message, request_id, doc_url } }. Codes you should branch on include:

typemeaning
validation_errormalformed request; the message names the field
invalid_key / revoked_key / expired_tokencredential problems; only expired_token is fixed by minting a new token
feature_disabled / feature_not_assignedthe feature isn't enabled for your tenant
unsupported_image_formatnot a decodable JPEG, PNG, WebP, TIFF, BMP or HEIC
image_too_largea side is over 40 megapixels; resize and resend
no_face_detected / multiple_faces_detected / low_quality_faceface-input problems on the face endpoints; prompt a retake
no_face / multiple_faces / low_image_qualitythe same on the liveness endpoint
frame_replayed / challenge_token_invalidliveness frames already scored, or a stale challenge token; capture fresh frames and mint a new challenge
rate_limitedback off for retry_after_ms and retry

A liveness check that ran but did not pass is not an error: it is a 200 with is_live: false and a reason such as challenge_action_not_detected. See Liveness checks.

Timeouts surface as EkycError with status: 0 and message Request timed out (configurable via timeout). The SDK does not retry on its own. A request_id accompanies every response; logging it alongside your own correlation ids makes support turnaround immediate.

The full error catalogue is in the Errors concept page.