Skip to main content

Error Handling

The SDK throws typed errors that you can catch and inspect.

Error types

ClassWhen thrown
DelhiveryErrorGeneric API error (4xx/5xx)
DelhiveryAuthError401/403 — invalid or expired token
DelhiveryRateLimitError429 — too many requests
DelhiveryNetworkErrorNetwork failure (timeout, DNS, etc.)

All classes are exported from delhivery-sdk.

Catching specific errors

import {
DelhiveryClient,
DelhiveryAuthError,
DelhiveryRateLimitError,
DelhiveryNetworkError,
DelhiveryError,
} from "delhivery-sdk";

const client = new DelhiveryClient({ token: process.env.DELHIVERY_TOKEN! });

try {
const data = await client.tracking.trackOne("1234567890");
} catch (err) {
if (err instanceof DelhiveryAuthError) {
console.error("Check your API token.");
} else if (err instanceof DelhiveryRateLimitError) {
console.error("Slow down — rate limit hit.");
} else if (err instanceof DelhiveryNetworkError) {
console.error("Network issue:", err.message);
} else if (err instanceof DelhiveryError) {
console.error(`API error ${err.statusCode}:`, err.message, err.raw);
} else {
throw err; // unexpected
}
}

Inspecting the raw response

DelhiveryError exposes the raw API response body as err.raw:

} catch (err) {
if (err instanceof DelhiveryError) {
console.log(err.statusCode); // 422
console.log(err.raw); // { error: "Invalid pincode" }
}
}

Retrying with exponential back-off

For transient errors (network timeouts, 5xx), implement a simple retry wrapper:

async function withRetry<T>(
fn: () => Promise<T>,
retries = 3,
): Promise<T> {
for (let attempt = 0; attempt < retries; attempt++) {
try {
return await fn();
} catch (err) {
const isTransient =
err instanceof DelhiveryNetworkError ||
(err instanceof DelhiveryError && err.statusCode >= 500);

if (!isTransient || attempt === retries - 1) throw err;

await new Promise((r) =>
setTimeout(r, 2 ** attempt * 500), // 500ms, 1s, 2s
);
}
}
throw new Error("unreachable");
}

const data = await withRetry(() => client.tracking.trackOne("1234567890"));