> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pramaan.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Error codes, HTTP statuses and what to do about each.

Every error has the same shape:

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "query is missing or invalid.",
    "request_id": "req_01J...",
    "next": "Fix the fields named in the message and send again.",
    "retryable": false
  }
}
```

`message` is at most 200 characters and never echoes your input. `retryable: true` means the
same request may succeed later. `next` is a short instruction for your next step (at most 200 characters).
For actions, check whether anything happened before retrying; keep the same Idempotency-Key.

`effect: "none"` means nothing was sent, charged or created: every source refused before
acting, or the request was refused before anything ran (validation, approval, credit, limits).
It is safe to change the request and try again. When `effect` is absent, a send, payment or
purchase may have happened: check before retrying, and retry with the same `Idempotency-Key`.
A failed job's `error` carries the same field.

| Code | HTTP | What to do |
| - | - | - |
| `invalid_request` | 400 | Fix the request body; the capability's reference page shows the schema. |
| `unauthorized` | 401 | Check the API key; it may be revoked. |
| `spend_cap_reached` | 402 | Top up credits, or raise the daily spend cap in the dashboard. |
| `addendum_required` | 403 | A hiring or court-record superpower needs the background-checks addendum: an owner or admin accepts it in Settings, or with `POST /v1/workspace/addenda`. Nothing ran or was charged. |
| `not_found` | 404 | Check the capability id. |
| `job_not_found` | 404 | The job id is wrong, belongs to another account, or is older than 7 days. |
| `conflict` | 409 | An `Idempotency-Key` was reused with a different body, or the first request is still running (`retryable: true`). |
| `connection_required` | 409 | Connect an account for the returned `slot` (see [connections](https://docs.pramaan.dev/guides/connections.md)). |
| `rate_limited` | 429 | Wait for the `Retry-After` seconds, then retry. |
| `internal` | 500 | Retry later; quote the `request_id` if it persists. |
| `upstream_unavailable` | 502 | The service behind the capability failed. Retry with backoff. |
| `upstream_timeout` | 504 | The call took longer than 25 seconds. Retry, or use a smaller request. |

## In the SDK

The SDK throws `PramaanError` with `code`, `message`, `next`, `retryable`, `requestId`, `status`,
`effect` (`"none"` or absent) and, for `connection_required`, `slot`.

```ts theme={null}
import { PramaanError } from "@pramaan/sdk";

try {
  await p.web.search({ query: "" });
} catch (error) {
  if (error instanceof PramaanError && error.code === "invalid_request") {
    console.log(error.message, error.requestId);
  }
}
```

The SDK retries `429` and `5xx` responses (and network failures) for read-only capabilities,
up to two times with backoff, sending the same `Idempotency-Key` each time (a retry that finds
the first attempt still in progress reports the first attempt's error). It never retries
capabilities with an external effect, such as sending an email; you decide when to retry those.

## Default next instructions

| Code | Next |
| - | - |
| `invalid_request` | Fix the fields named in the message and send again. |
| `unauthorized` | Send a valid API key in the Authorization header. |
| `forbidden` | Ask an account owner for access or the approval named in the message. |
| `addendum_required` | Ask a workspace owner or admin to accept the background-checks addendum in Settings. |
| `spend_cap_reached` | Top up credit or raise the daily cap in the dashboard. |
| `not_found` | Check the id or reference you sent; list the items first to get a valid one. |
| `job_not_found` | Check the job id; use the id returned when you started the job. |
| `conflict` | Retry the same request with the same Idempotency-Key; use a new key only for a new request. |
| `connection_required` | Connect the account with apps.connection.start, then retry. |
| `rate_limited` | Wait for Retry-After seconds, then retry; if absent, wait a minute. |
| `internal` | Retry later; if it keeps failing, contact [support@pramaan.dev](mailto:support@pramaan.dev) with request\_id. |
| `upstream_unavailable` | Try again in a minute; check whether an action happened before retrying it. |
| `upstream_timeout` | Check whether an action happened; retry with the same Idempotency-Key if needed. |

When `retryable` is `false`, these codes get a default that never asks for a retry:

| Code | Next when not retryable |
| - | - |
| `conflict` | Check the current state named in the message; use a new Idempotency-Key only for a new request. |
| `rate_limited` | Wait for the limit named in the message to reset before sending more. |
| `internal` | Contact [support@pramaan.dev](mailto:support@pramaan.dev) with the request\_id; sending the same request again will not help. |
| `upstream_unavailable` | Do not resend it as is: check whether an action happened, then use a similar superpower or contact [support@pramaan.dev](mailto:support@pramaan.dev) with the request\_id. |
| `upstream_timeout` | Check whether an action happened before sending anything again; do not resend it blindly. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.