> Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

---
title: Errors
description: Error format and how to handle each case.
---

# Errors

Errors are returned with a standard JSON envelope and an appropriate HTTP status
code. The status code is also mirrored inside the body.

```json
{
  "error": {
    "status_code": 422,
    "code": "voice_language_not_found",
    "message": "No voice named 'Mohan' found for language 'ta-IN'. Use GET /v1/voices to see valid combinations."
  }
}
```

* `status_code` — the HTTP status.
* `code` — a stable, machine-readable identifier you can branch on.
* `message` — a human-readable description of what went wrong and how to fix it.

## Status codes

| Status | Code(s)                                                                             | Meaning                                           |
| ------ | ----------------------------------------------------------------------------------- | ------------------------------------------------- |
| 401    | `invalid_api_key`                                                                   | Missing, invalid, or revoked API key.             |
| 402    | `insufficient_credits`                                                              | Not enough credits for the request.               |
| 422    | `text_too_long`, `voice_language_not_found`, `invalid_model_id`, `validation_error` | Request body failed validation.                   |
| 429    | `rate_limit_exceeded`, `concurrency_limit_exceeded`                                 | Too many requests, or too many in flight at once. |
| 503    | `tts_workers_busy`, `tts_workers_unconfigured`                                      | Speech workers are unavailable or at capacity.    |
| 500    | `internal_error`                                                                    | Unexpected server error. Retry with backoff.      |

## Validation errors (422)

Common causes:

* **`text_too_long`** — input exceeds 3000 Unicode characters.
* **`voice_language_not_found`** — the `voice` + `language` pair is invalid.
* **`invalid_model_id`** — `model_id` is not a supported model. Use `raaga-v1`.
* **`validation_error`** — a field failed schema validation, such as an
  unsupported `output_format` (must be `mp3`, `wav`, `pcm`, or `mulaw`), an
  unsupported `sample_rate`, or a `speed` outside its allowed range. The
  `message` names the offending field.

## Worker availability (503)

If synthesis capacity is momentarily unavailable, you receive
`503 Service Unavailable`:

* **`tts_workers_busy`** — synthesis capacity is full right now. Retry shortly
  with backoff.
* **`tts_workers_unconfigured`** — the synthesis service is temporarily
  unavailable. Retry shortly.

## Rate and concurrency limits (429)

Two distinct conditions return `429`:

* **`rate_limit_exceeded`** — you started too many requests in the current
  minute. Includes a `Retry-After` header (and `retry_after_seconds` over
  WebSocket); retry after that delay.
* **`concurrency_limit_exceeded`** — your account already has the maximum number
  of synthesis requests in flight at once. This has **no `Retry-After`**, since
  the slot frees only when one of your other in-flight requests finishes. Retry
  once an outstanding request completes.

See [Rate Limits](/concepts/rate-limits) for plan-specific values and how each
limit is counted.

## WebSocket errors

Per-message errors over WebSocket are delivered as JSON `error` messages and the
connection stays open:

```json
{
  "type": "error",
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Retry after 12 seconds.",
    "retry_after_seconds": 12
  }
}
```

Connection-level failures close the socket:

| Code | Reason                                                                        |
| ---- | ----------------------------------------------------------------------------- |
| 1000 | Normal closure                                                                |
| 1011 | Session lost (concurrency or worker capacity revoked mid-session) — reconnect |
| 4001 | Authentication failed                                                         |
| 4002 | Internal server error                                                         |

## Typed errors in the SDKs

Both SDKs map the envelope into typed exceptions so you can handle each case
directly.

#### Python

```python
from vakyamai import (
    AuthenticationError,
    InsufficientCreditsError,
    RateLimitError,
    ValidationError,
    APIError,
)

try:
    client.tts.generate(
        text="...", model_id="raaga-v1", voice="Archana", language="ta-IN",
    )
except RateLimitError as exc:
    print("retry after", exc.retry_after_seconds)
except ValidationError as exc:
    print(exc.code, exc.message)
```



#### JavaScript

```ts
import { VakyamAPIError } from "@vakyam-ai/tts";

try {
  await client.tts.generate({
    text: "...", model_id: "raaga-v1", voice: "Archana", language: "ta-IN",
  });
} catch (err) {
  if (err instanceof VakyamAPIError) {
    console.error(err.statusCode, err.code, err.message);
  }
}
```

---

*Powered by [holocron.so](https://holocron.so)*
