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

# Errors

> What comes back, and what to do about it.

Errors are JSON, whatever the endpoint:

```json theme={null}
{
  "error": "invalid_key",
  "request_id": "7c0f5792-aa4c-4b58-a042-328d21feb90a"
}
```

<Tip>
  Keep the `request_id`. It is what lets us find your exact request.
</Tip>

| Status    | Error                  | What to do                                              |
| :-------- | :--------------------- | :------------------------------------------------------ |
| 401       | `invalid_key`          | Check the key — [paste, never retype](/authentication). |
| 400       | `text_required`        | `text` was missing or empty.                            |
| 400       | `text_too_long`        | Response carries `max` and `got`.                       |
| 400       | `unknown_voice`        | Response lists the valid ones. Case matters.            |
| 400       | `invalid_request`      | Wrong **type** for a field — the response names it.     |
| 402 / 429 | `insufficient_credits` | Out of credits. Retrying will not help.                 |
| 429       | `concurrency_exceeded` | Too many at once. Back off and retry.                   |
| 503       | `tts_not_configured`   | Ours, not yours. Retry shortly.                         |

## Retry only what retrying fixes

`concurrency_exceeded` is worth a backoff. `insufficient_credits`,
`unknown_voice` and `text_too_long` will fail identically forever — read the
message instead.

## On the WebSocket

Errors arrive as frames and the socket **stays open**. Correct the frame and
send it again:

```json theme={null}
{
  "type": "error",
  "error": "invalid 'voice'",
  "available_voices": ["Ananya", "Arjun"]
}
```
