---
title: "Error Handling"
description: "Catch and inspect API errors, configure retries, and use idempotency keys in the PgBeam TypeScript SDK."
canonical: "https://pgbeam.com/docs/ts-sdk/error-handling"
last-updated: "2026-09-14T19:37:21.000Z"
---

# Error Handling

> Catch and inspect API errors, configure retries, and use idempotency keys in the PgBeam TypeScript SDK.

URL: https://pgbeam.com/docs/ts-sdk/error-handling

All non-2xx responses throw an `ApiError`:

## ApiError properties

Every error the API returns is an RFC 9457 problem document, and `ApiError` lifts its fields onto itself so you do not have to reach into `body`.

Property

Type

Description

`status`

`number`

HTTP status code

`statusText`

`string`

HTTP status text

`code`

`string \| undefined`

Stable identity of the condition, e.g. `PLAN_LIMIT_REACHED`

`type`

`string \| undefined`

The same identity as a URI, resolving to the error catalog

`title`

`string \| undefined`

Short summary of the condition

`detail`

`string \| undefined`

Explanation of this occurrence. Same value as `message`

`instance`

`string \| undefined`

Path of the request that produced the error

`requestId`

`string \| undefined`

Correlation id, also in the `X-Request-Id` header

`errors`

`ApiFieldError[] \| undefined`

Field-level detail when the request failed validation

`message`

`string`

`detail`, falling back to the status text

`body`

`unknown`

Parsed response body

## Branch on `code`, not on `message`

`code` is stable across wording changes and separates conditions that share a status. A `403` is either a permissions problem or a billing one, and those are resolved in completely different ways.

## extractMessage helper

Pulls the human-readable message out of an error body: the problem document's `detail`, falling back to the older `{ error: { message } }` and `{ message }` shapes that non-control-plane endpoints still answer with.

See the error catalog for every code the API can return.

## Retries

The SDK automatically retries transient errors with exponential backoff. Non-retryable errors are thrown immediately.

**Retried:** 408, 429, 502, 503, 504, and network errors (connection refused, DNS failure, fetch error). All other status codes are **not** retried.

When the server returns a `Retry-After` header (on 429 or 503), the SDK uses that value instead of its own computed backoff.

See Response Conventions for the backoff formula and retry behavior details.

## Retry configuration

Option

Type

Default

Description

`maxRetries`

`number`

`5`

Max retry attempts after the initial request. `0` disables retries.

`initialDelayMs`

`number`

`500`

Initial backoff delay in milliseconds.

`maxDelayMs`

`number`

`30000`

Maximum backoff delay in milliseconds.

`idempotencyKeys`

`boolean`

`true`

Auto-send `Idempotency-Key` header on POST/PATCH.

## Disabling retries

## Idempotency

When `idempotencyKeys` is enabled (the default), POST and PATCH requests include an `Idempotency-Key` header so retries never double-create resources. The server caches responses for 24 hours.

See Response Conventions for how idempotency keys work.