Skip to main content

Error recovery

Graceful error handling patterns for transient failures.

Retry with exponential backoff

import {
ApiError,
Conduit,
RateLimitError,
} from "@mappa-ai/conduit"

const conduitClient = new Conduit({ apiKey: process.env.CONDUIT_API_KEY! })

async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3, baseDelay = 1000): Promise<T> {
let last: Error | undefined

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn()
} catch (error) {
last = error as Error

if (error instanceof ApiError && error.status < 500 && !(error instanceof RateLimitError)) {
throw error
}

const delay = error instanceof RateLimitError && error.retryAfterMs
? error.retryAfterMs
: baseDelay * 2 ** attempt

await new Promise((resolve) => setTimeout(resolve, delay))
}
}

throw last ?? new Error("Retry budget exhausted")
}

const receipt = await withRetry(() =>
conduitClient.reports.create({
source: { url: "https://example.com/recording.mp3" },
output: { template: "general_report" },
target: { strategy: "dominant" },
webhook: { url: "https://your-app.com/webhooks/conduit" },
}),
)