# Errors

> Every error has a stable code, a type that maps to an HTTP status, and a request id to quote when you contact support.

Source: https://docs.borga.is/errors

Errors share one envelope. `type` tells you the class of problem and maps to the HTTP status; `code` is a stable identifier to branch on; `message` is for humans and may change; `param` names the offending field when there is one.

```json Error response
{
  "error": {
    "type": "invalid_request_error",
    "code": "redirect_url_not_allowed",
    "message": "Domain \"shop.example\" is not in the merchant's allowed redirect domains.",
    "param": "return_url",
    "doc_url": "https://docs.borga.is/errors/redirect_url_not_allowed",
    "request_id": "req_95ef3682c9474dcd99cc31cab949a5e2"
  }
}
```

Each `code` has a page at `/errors/<code>`, which is what `doc_url` points to. The `request_id` is also sent as the `X-Request-Id` response header on every request; include it when writing to support.

## Error types

_(ErrorTypes table: see the HTML page)_

## Handling errors in code

The Node SDK throws `BorgaError` for every non-2xx response and for network failures, with the envelope's fields as properties. It retries `429` and `5xx` responses and network errors up to three times with exponential backoff before throwing.

```ts Node.js

const borga = new Borga({ apiKey: process.env.BORGA_SECRET_KEY! });

try {
  await borga.paymentSessions.create({
    amount: 1990,
    currency: "ISK",
    return_url: "https://yoursite.is/complete",
    cancel_url: "https://yoursite.is/cart",
  });
} catch (err) {
  if (err instanceof BorgaError) {
    // err.code is stable and safe to branch on; err.message is for humans.
    if (err.code === "redirect_url_not_allowed") {
      console.error(`Add the domain in the dashboard (${err.param})`);
    } else if (err.status === 429) {
      // The SDK already retried; back off further.
    }
    console.error(`[${err.requestId}] ${err.type}/${err.code}: ${err.message}`);
  } else {
    throw err;
  }
}
```

Branch on `code`, never on `message`. Treat unknown codes as failures of their `type`: new codes are added over time.

## Validation errors

Request bodies are validated before anything else runs. Unknown fields are stripped silently; wrong types or constraint violations return `validation_failed` with the first failing rule in `message` and the field in `param`.

## All error codes

_(ErrorCodes table: see the HTML page)_
