AI Error Handling
Build resilient AI integrations with exponential backoff, rate limit recovery, circuit breakers, and fallback models.
TL;DR
- Catch
RateLimitErrorHTTP 429 exceptions and back off with randomized jitter. - Configure
exponential-backoffalgorithms to survive temporary upstream API outages. - Implement multi-provider
model-fallbacksto preserve application uptime during downtime.
Common AI Error Classes
RateLimitError (429)Triggered when exceeding RPM or TPM account limits.
if (error instanceof OpenAI.RateLimitError) {
const delaySec = error.headers?.['retry-after'];
console.warn(`Retry after ${delaySec}s`);
}Timeout ErrorsOccurs when network requests fail to complete within target deadline.
const isTimeout =
error instanceof OpenAI.APIConnectionTimeoutError;
if (isTimeout) console.warn('AI request timed out');BadRequestError (400)Permanent validation errors such as invalid schemas or missing fields.
if (error instanceof OpenAI.BadRequestError) {
// Do NOT retry; inspect payload parameters
}Exponential Backoff With Jitter
Calculate Backoff DelayCompute exponential delay with full randomized jitter distribution.
function getDelay(i: number, base = 500) {
const exp = Math.min(base * (2 ** i), 10000);
return Math.floor(Math.random() * exp);
}Retry Loop ImplementationExecute request loop with maximum retry attempt bounds.
async function retry<T>(
fn: () => Promise<T>
): Promise<T> {
for (let i = 0; i < 3; i++) {
try { return await fn(); }
catch (err) {
if (i === 2 || !isRetryable(err)) throw err;
const ms = getDelay(i);
await new Promise(r => setTimeout(r, ms));
}
}
throw new Error('Retries exhausted');
}IsRetryable CheckFilter error status codes that represent transient network issues.
function isRetryable(err: any): boolean {
const s = err.status ?? err.statusCode;
return s === 429 || (s >= 500 && s < 600);
}Model Fallbacks
Provider Fallback ChainFail over to alternate provider model when primary model fails.
async function callAI(prompt: string) {
try {
return await callClaude(
'claude-3-5-sonnet', prompt
);
} catch (err) {
console.warn('Claude failed, trying OpenAI');
return await callOpenAI('gpt-4o', prompt);
}
}Tier DegradationDegrade to faster model if frontier model suffers capacity outage.
try {
return await callModel('gpt-4o', prompt);
} catch (err) {
return await callModel('gpt-4o-mini', prompt);
}Cached Response FallbackServe stale cached completion when all upstream providers are unreachable.
const fallback = await cache.get(promptHash);
if (fallback) return fallback;Circuit Breaker Pattern
Circuit State MachineTrack CLOSED, OPEN, and HALF_OPEN states based on recent failures.
enum CircuitState { CLOSED, OPEN, HALF_OPEN }
let state = CircuitState.CLOSED;
let consecutiveFailures = 0;Fast Failure In Open StateReject incoming calls immediately without hitting network when OPEN.
if (state === CircuitState.OPEN) {
if (Date.now() - lastFailureTime > 30000) {
state = CircuitState.HALF_OPEN;
} else {
throw new Error('Circuit open: service down');
}
}State Reset On SuccessReset failure counters when probe request succeeds in HALF_OPEN state.
function recordSuccess() {
consecutiveFailures = 0;
state = CircuitState.CLOSED;
}Tips
- Inspect the
retry-afterheader on HTTP 429 responses to delay the subsequent attempt by the exact duration requested by the provider. - Wrap AI client requests in
circuit-breakersto fail fast when error rates exceed acceptable operational thresholds.
Warnings
- Never retry non-idempotent or non-retryable errors like
401 Unauthorizedor400 BadRequestbecause they will never succeed without code changes. - Avoid retrying immediately without
random-jitterbecause thousands of concurrent workers retrying at identical intervals create severe thundering herds.
In Practice
Wraps AI completion calls with exponential backoff, jitter, and automatic failover from Claude to OpenAI.
- Define retryable error predicate checking status 429 and 5xx errors.
- Implement jittered exponential delay calculator.
- Attempt primary Claude call with up to 3 jittered retries.
- Fail over automatically to secondary OpenAI provider if retries exhaust.
import Anthropic from '@anthropic-ai/sdk';
import OpenAI from 'openai';
const [claude, gpt] = [new Anthropic(), new OpenAI()];
async function runSafe(prompt: string) {
const messages = [{ role: 'user', content: prompt }];
try {
const res = await claude.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 150, messages,
});
const b = res.content[0] as any;
return b?.text ?? '';
} catch {
const fb = await gpt.chat.completions.create({
model: 'gpt-4o', messages,
});
return fb.choices[0]?.message?.content ?? '';
}
}
await runSafe('Hello AI');FAQ
HTTP 429 occurs when your application exceeds account tier quotas for Requests Per Minute (RPM), Tokens Per Minute (TPM), or daily spend limits. Slowing down request concurrency or requesting tier upgrades resolves this.
Without jitter, multiple client requests throttled at the same time will retry on identical schedules, repeatedly slamming the API in synchronized spikes. Adding random jitter spreads retries evenly across the timeline.
A circuit breaker monitors failure rates. When provider errors exceed a threshold (e.g. 50% over 1 minute), the breaker opens, failing requests immediately or routing to fallback models without wasting time on failing network calls.