> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.meshapi.ai/llms.txt.
> For full documentation content, see https://developers.meshapi.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.meshapi.ai/_mcp/server.

# Error Handling

> Handle errors and retries in the Python SDK.

# Error Handling

```python
from meshapi import MeshAPIError

try:
    client.chat.completions.create(params)
except MeshAPIError as e:
    print(f"[{e.status}] {e.error_code}: {e}")
    print("Request ID:", e.request_id)

    if e.error_code == "rate_limit_exceeded":
        print(f"Retry after {e.retry_after_seconds}s")
    elif e.error_code == "spend_limit_exceeded":
        print("Account balance exhausted. Top up to continue.")
    elif e.error_code == "unauthorized":
        print("Invalid API key.")
    elif e.error_code == "model_not_found":
        print("Model not supported.")
    elif e.error_code == "upstream_error":
        print("Provider error:", e.provider_error)
    elif e.error_code == "validation_error":
        print("Invalid request:", e.details)
```

| Code                                                    | HTTP | Meaning                                      |
| ------------------------------------------------------- | ---- | -------------------------------------------- |
| `unauthorized`                                          | 401  | Invalid or missing key                       |
| `forbidden`                                             | 403  | Key suspended                                |
| `not_found` / `model_not_found`                         | 404  | Resource or model not found                  |
| `spend_limit_exceeded`                                  | 402  | Account balance at zero. Top up to continue. |
| `validation_error` / `unprocessable_entity`             | 422  | Bad request body                             |
| `rate_limit_exceeded`                                   | 429  | RPM or RPD limit hit                         |
| `upstream_error` / `gateway_timeout` / `internal_error` | 500  | Upstream or server error                     |
| `parse_error`                                           | n/a  | SDK could not parse response body            |
| `stream_interrupted`                                    | n/a  | Mid-stream connection dropped                |

Mid-stream errors (sent as SSE frames before `[DONE]`) raise the same `MeshAPIError` from inside the iterator.

## Retry and backoff

The client automatically retries `GET` and non-streaming `POST` / `PATCH` requests on status codes `429`, `502`, `503`, `504` with exponential backoff (default: 3 retries, base delay 500 ms, max 30 s, with jitter). The `Retry-After` header is respected on 429 responses.

```python
client = MeshAPI(
    base_url="https://api.meshapi.ai",
    token="rsk_...",
    max_retries=5,   # 0 to disable
    timeout=30.0,
)
```

## Streaming failure recovery

**Streams do not retry.** If a connection drops mid-stream, a `MeshAPIError` with `error_code="stream_interrupted"` is raised. Catch it and restart a new request:

```python
try:
    for chunk in client.chat.completions.stream(params):
        process(chunk)
except MeshAPIError as e:
    if e.error_code == "stream_interrupted":
        # restart from scratch
        ...
```