--- category: SDK title: Error Handling description: "Handle errors and implement retry strategies with the openstatus Node.js SDK" --- The SDK uses ConnectRPC. Errors are thrown as `ConnectError` instances from the `@connectrpc/connect` package. ```typescript import { ConnectError } from "@connectrpc/connect"; try { await client.monitor.v1.MonitorService.deleteMonitor({ id: "invalid" }); } catch (error) { if (error instanceof ConnectError) { console.error(`Code: ${error.code}`); console.error(`Message: ${error.message}`); } } ``` ## Common Error Codes | Code | Description | |------|-------------| | `unauthenticated` | Missing or invalid API key | | `not_found` | Resource does not exist | | `invalid_argument` | Validation failure (e.g., missing required field, value out of range) | | `permission_denied` | No access to this workspace or resource | | `already_exists` | Duplicate resource (e.g., slug already taken) | | `resource_exhausted` | Rate limited (HTTP `429`); wait for the `Retry-After` header, see [API rate limits](/docs/reference/api-rate-limits) | | `unavailable` | The server is shedding load (HTTP `503`); retry with backoff | ## Retry Strategy ConnectRPC does not retry by default. For transient failures (`resource_exhausted`, `unavailable`, `deadline_exceeded`), implement your own retry logic. The response headers, including `Retry-After`, are available on `error.metadata`; keep the delay at or above that value when it is present: ```typescript import { Code, ConnectError } from "@connectrpc/connect"; async function withRetry(fn: () => Promise, maxRetries = 3): Promise { for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { if ( error instanceof ConnectError && (error.code === Code.ResourceExhausted || error.code === Code.Unavailable || error.code === Code.DeadlineExceeded) && attempt < maxRetries ) { const retryAfter = Number(error.metadata.get("retry-after")) * 1000; const backoff = 1000 * 2 ** attempt; await new Promise((resolve) => setTimeout(resolve, Math.max(retryAfter || 0, backoff)), ); continue; } throw error; } } throw new Error("Unreachable"); } const { httpMonitors } = await withRetry(() => client.monitor.v1.MonitorService.listMonitors({}) ); ```