Skip to main content

Error Handling

Both SDKs use typed error classes that extend a base OptropicError. Every error includes a machine-readable code, HTTP status, and human-readable message.

Error Hierarchyโ€‹

OptropicError
โ”œโ”€โ”€ AuthenticationError (401 โ€” invalid or expired API key)
โ”œโ”€โ”€ ForbiddenError (403 โ€” insufficient permissions) [Python only]
โ”œโ”€โ”€ NotFoundError (404 โ€” resource not found) [Python only]
โ”œโ”€โ”€ ValidationError (400 โ€” invalid request body) [Python only]
โ”œโ”€โ”€ InvalidSerialError (400 โ€” malformed serial)
โ”œโ”€โ”€ InvalidGTINError (400 โ€” malformed GTIN)
โ”œโ”€โ”€ InvalidCodeError (400 โ€” malformed code format)
โ”œโ”€โ”€ CodeNotFoundError (404 โ€” serial not found)
โ”œโ”€โ”€ BatchNotFoundError (404 โ€” batch not found)
โ”œโ”€โ”€ RevokedCodeError (410 โ€” asset revoked)
โ”œโ”€โ”€ RateLimitedError (429 โ€” rate limit exceeded)
โ”œโ”€โ”€ QuotaExceededError (429 โ€” monthly quota reached)
โ”œโ”€โ”€ NetworkError (0 โ€” connection failed)
โ”œโ”€โ”€ TimeoutError (0 โ€” request timed out)
โ””โ”€โ”€ ServiceUnavailableError (503 โ€” server temporarily down)

Catching Errorsโ€‹

import { OptropicError, RateLimitedError, AuthenticationError } from 'optropic';

try {
const asset = await client.assets.verify('SER-invalid');
} catch (err) {
if (err instanceof RateLimitedError) {
// Back off and retry
console.log(`Rate limited. Retry after: ${err.message}`);
} else if (err instanceof AuthenticationError) {
// Check API key
console.error('Invalid API key');
} else if (err instanceof OptropicError) {
// All other API errors
console.error(`[${err.code}] ${err.message} (HTTP ${err.status})`);
} else {
throw err; // Not an Optropic error
}
}

Automatic Retriesโ€‹

The SDK automatically retries on transient errors (429, 500, 502, 503, 504) using exponential backoff with jitter:

delay = min(base_delay ร— 2^attempt, max_delay) + (delay ร— 0.5 ร— random())

Default configuration: 3 retries, 1s base delay, 10s max delay. This prevents thundering herd effects when multiple clients retry simultaneously.

Idempotencyโ€‹

POST, PUT, and PATCH requests automatically include an Idempotency-Key header (UUID v4). This means retries are safe โ€” the server deduplicates requests with the same idempotency key. GET and DELETE requests do not include this header.