Error Handling
The SDK provides a hierarchy of typed error classes so you can handle API failures precisely with instanceof checks. It also automatically retries transient failures, so your code handles fewer edge cases.
Error Hierarchy
All SDK errors extend the base OcrivaError class:
OcrivaError ← base class for all SDK errors
└── ApiError ← non-2xx HTTP responses (has statusCode, error)
├── AuthenticationError ← 401 Unauthorized
├── RateLimitError ← 429 Too Many Requests (has retryAfter)
└── NotFoundError ← 404 Not FoundThe OcrivaError base class is also thrown directly for configuration errors (e.g., missing API key, invalid baseUrl) and network-level failures (e.g., timeout, DNS failure).
Catching Errors
Import the error classes alongside the client:
import {
OcrivaClient,
OcrivaError,
ApiError,
AuthenticationError,
RateLimitError,
NotFoundError,
} from '@ocriva/sdk';
const client = new OcrivaClient({ apiKey: process.env.OCRIVA_API_KEY! });
try {
const record = await client.processingHistory.get('hist_abc123', 'proj_abc123');
console.log(record.status);
} catch (error) {
if (error instanceof AuthenticationError) {
// 401 — API key is invalid, expired, or does not have access to this resource
console.error('Authentication failed. Check your API key.');
} else if (error instanceof RateLimitError) {
// 429 — too many requests; the SDK already retried maxRetries times
console.error(`Rate limited. Retry after ${error.retryAfter ?? 'unknown'} seconds.`);
} else if (error instanceof NotFoundError) {
// 404 — the requested resource does not exist
console.error('Record not found:', error.message);
} else if (error instanceof ApiError) {
// Any other non-2xx response (400, 403, 500, etc.)
console.error(`API error ${error.statusCode}: ${error.message}`);
} else if (error instanceof OcrivaError) {
// Network timeout, invalid config, or unknown SDK error
console.error('SDK error:', error.message);
} else {
// Unexpected non-SDK error
throw error;
}
}Error Properties
OcrivaError
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error description |
name | string | Error class name (e.g., 'AuthenticationError') |
ApiError
| Property | Type | Description |
|---|---|---|
statusCode | number | HTTP status code returned by the API |
message | string | Error message from the API response body |
error | string | undefined | Short error classification (e.g., 'Unauthorized') |
RateLimitError
| Property | Type | Description |
|---|---|---|
statusCode | number | Always 429 |
retryAfter | number | undefined | Seconds to wait before retrying, parsed from the Retry-After response header |
} catch (error) {
if (error instanceof RateLimitError && error.retryAfter !== undefined) {
// Manually wait and retry if you have disabled automatic retries
await new Promise((resolve) => setTimeout(resolve, error.retryAfter! * 1000));
}
}Automatic Retries
The SDK automatically retries failed requests when the server returns a 429 or a 5xx response. Retries use exponential backoff with a 1-second base and a 30-second cap:
| Attempt | Delay before retry |
|---|---|
| 1st retry | 1 s |
| 2nd retry | 2 s |
| 3rd retry | 4 s |
For 429 responses, the SDK respects the Retry-After header from the server instead of using backoff, if present.
The number of retries is controlled by the maxRetries option (default: 3). Set it to 0 to disable automatic retries entirely:
const client = new OcrivaClient({
apiKey: process.env.OCRIVA_API_KEY!,
maxRetries: 0, // disable automatic retries
});Once all retries are exhausted, the SDK throws the corresponding error (RateLimitError for 429, ApiError for 5xx).
Rate Limiting
The Ocriva API allows 60 requests per minute per API key. If you exceed this limit, the API returns 429 Too Many Requests.
In most cases the SDK handles this transparently — it pauses and retries until the rate limit window resets. If retries are exhausted or you have disabled them, a RateLimitError is thrown.
To avoid hitting the rate limit in bulk operations, consider:
- Using the batch resource to group many files into a single API call instead of uploading them one by one.
- Adding deliberate delays between requests in tight loops.
For advanced rate limiting strategies including manual backoff implementation, see Retry & Rate Limiting.
Request Timeouts
Each request has a configurable timeout (default: 30,000 ms). If a request exceeds the timeout, the SDK throws an OcrivaError with a message like Request timed out after 30000ms.
const client = new OcrivaClient({
apiKey: process.env.OCRIVA_API_KEY!,
timeout: 60_000, // increase to 60 s for large file uploads
});Debugging Tips
Enable verbose logging
When an error is hard to diagnose, log all available properties before letting the error propagate:
try {
const result = await client.upload.create({ ... });
} catch (error) {
if (error instanceof ApiError) {
console.error('Status:', error.statusCode);
console.error('Message:', error.message);
console.error('Error:', error.error);
}
// For network errors, log the full error
console.error('Full error:', error);
}Check Processing History
After an upload, if the result looks unexpected (empty extraction, wrong fields), retrieve the processing record directly to inspect its detailed status and any server-side error messages:
const record = await client.processingHistory.get(result.historyId, 'proj_abc123');
console.log('Status:', record.status);
console.log('Error:', record.errorMessage);Verify API key scope
A common source of 401 and 403 errors is using an organization-level API token against a project-scoped endpoint, or vice versa. Open Organization → API Tokens in the dashboard and confirm that the token type matches the resource you are calling.
Test with small payloads first
Before running a batch job, test the same template and model configuration with a single document. This surfaces template misconfiguration and provider errors early, at low cost.
Common Error Reference
| Status | Error Class | Typical Cause |
|---|---|---|
400 | ApiError | Missing or invalid parameters (check error.message for field details) |
401 | AuthenticationError | Invalid or expired API key, or token-project mismatch |
403 | ApiError | IP not whitelisted, or token lacks permission for the resource |
404 | NotFoundError | Resource does not exist or belongs to a different project |
429 | RateLimitError | Rate limit exceeded (auto-retried up to maxRetries times) |
500 | ApiError | Server error (auto-retried; contact support if it persists) |
| — | OcrivaError | Network timeout, DNS failure, or invalid client configuration |
For a comprehensive error code catalog with detailed solutions, see Error Code Reference.
