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

# Error Handling

> Interpret error responses and handle failures gracefully.

## The `success` Field

Every response from `POST /v1/query` includes a `success` boolean. Always check it first.

When `success` is `false`:

* `error` — a short, human-readable error message.
* `detailedError` — extended detail about the failure. May be absent for some error types. For parse errors, it includes the line and column position of the problem.

## HTTP Status Codes

| Status | Meaning                                                                                                  |
| ------ | -------------------------------------------------------------------------------------------------------- |
| `200`  | Request was processed. Check `success` — SQL errors return 200 with `success: false`.                    |
| `400`  | Malformed request body, SQL parse error, or unsupported SQL feature.                                     |
| `401`  | Missing or expired JWT, or token issued by the wrong Cognito pool.                                       |
| `403`  | Missing required scope (`query`) or tenantId mismatch.                                                   |
| `429`  | API rate limit exceeded. Retry with exponential backoff.                                                 |
| `500`  | Internal server error. Retry with exponential backoff. Include `x-request-id` when reporting to support. |

<Note>
  SQL errors (parse failures, unknown tables, unsupported features) are returned as **200 with `success: false`**, not as 400. A 400 indicates the request body itself was malformed — for example, missing the `sql` field or sending invalid JSON.
</Note>

## Parse Error Example

**Request (SQL typo):**

```json theme={null}
{
  "sql": "SELEKT id, name FROM myschema.users",
  "mode": "execute"
}
```

**Response:**

```json theme={null}
{
  "success": false,
  "error": "Parse error: unexpected token 'SELEKT'",
  "detailedError": "Parse error at line 1, column 1: unexpected token 'SELEKT'. Expected SELECT, WITH, or a set operation."
}
```

HTTP status: `400`

## Execution Error Example (200 with `success: false`)

**Request:**

```json theme={null}
{
  "sql": "SELECT * FROM myschema.nonexistent_table",
  "mode": "execute"
}
```

**Response:**

```json theme={null}
{
  "success": false,
  "error": "Table not found: myschema.nonexistent_table",
  "detailedError": "No table 'nonexistent_table' exists in schema 'myschema' for this tenant. Check that the table is registered in the portal under Settings > Data Sources."
}
```

HTTP status: `200`

## The `x-request-id` Header

Every response from the DynamoSQL Lambda includes an `x-request-id` response header. Save this value whenever you encounter a 500 error — include it when filing a support request so the DynamoSQL team can locate the relevant logs.

```
x-request-id: req_01HZ8KXMR3F9VW2BN6PQYT7GDE
```

## Retry Guidance

* **500s:** Retry with exponential backoff (e.g., 1s, 2s, 4s). These indicate a transient server-side failure.
* **429s:** Retry with exponential backoff. You have exceeded the per-tenant API call limit.
* **400 / 401 / 403:** Do not retry. These indicate a client-side error — fix the request, credentials, or token scopes before trying again.
* **200 with `success: false`:** Do not retry unless the error message suggests a transient condition. Most SQL errors are deterministic and will fail the same way on retry.

<Tip>
  When building a wrapper around DynamoSQL, distinguish between HTTP-level errors (non-200 status) and application-level errors (200 with `success: false`). They require different handling: one is a transport or auth issue, the other is a SQL or schema issue.
</Tip>
