Error Handling
GuideHandle API errors gracefully with typed exceptions and rate-limit retries. Examples shown for both Node.js and Python.
Error Codes Reference
| Code | HTTP | Description | Node.js | Python |
|---|---|---|---|---|
| invalid_request | 400 | Request parameters are invalid | BearLumenApiError | InvalidRequestError |
| authentication_error | 401 | API key is invalid or missing | BearLumenApiError | AuthenticationError |
| not_found | 404 | Requested resource does not exist | BearLumenApiError | NotFoundError |
| rate_limit_exceeded | 429 | Too many requests, retry after delay | BearLumenApiError | RateLimitError |
| server_error | 500 | Internal server error | BearLumenApiError | BearLumenError |
| network_error | - | Network connectivity issue | BearLumenApiError | NetworkError |
Basic Error Handling
Use instanceof checks with BearLumenApiError and switch on the error.code property:
import { BearLumen, BearLumenApiError } from '@bearlumen/node-sdk';
try {
const margins = await bear.margins.summary({
startDate: '2026-01-01',
endDate: '2026-01-31',
});
} catch (error) {
if (error instanceof BearLumenApiError) {
switch (error.code) {
case 'authentication_error':
console.error('Invalid API key');
break;
case 'rate_limit_exceeded':
console.error('Rate limited, retry after', error.retryAfter, 'seconds');
break;
case 'not_found':
console.error('Resource not found');
break;
default:
console.error('Error', error.code, error.message);
}
console.error('Request ID:', error.correlationId); // include in support tickets
}
}
Rate Limit Handling
When you hit a rate limit, the error.retryAfter property tells you how long to wait. Here is a simple retry pattern with exponential backoff:
import { BearLumenApiError } from '@bearlumen/node-sdk';
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3,
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (
error instanceof BearLumenApiError &&
error.code === 'rate_limit_exceeded' &&
attempt < maxRetries
) {
const delay = error.retryAfter
? error.retryAfter * 1000
: Math.pow(2, attempt) * 1000;
console.log('Rate limited. Retrying in', delay, 'ms...');
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
// Wrap any read query that might be rate limited.
const result = await withRetry(() =>
bear.usage.events({ startDate: '2026-01-01', endDate: '2026-01-31' })
);
Best Practices
- 1
Handle rate limits with exponential backoff. Respect the retryAfter / retry_after value when available, otherwise use increasing delays.
- 2
Flush before your process exits. track() batches events in the background, so call bear.shutdown() (or flush()) before exit, or queued events are lost.
- 3
Log error codes and request IDs for debugging. Error codes are stable identifiers for alerting and log analysis; the correlationId (Node.js) / request_id (Python) identifies the exact request in support tickets.
- 4
Use specific error types over generic catch-all. In Python, catch specific exceptions like RateLimitError before BearLumenError. In Node.js, check error.code for specific handling.