# Errors

Problems arrive as an `error` event with a short, human-readable message. Most
errors leave the connection open; auth, credit, and limit problems close it with
a [close code](events.html#close-codes).

```json
{
  "type": "error",
  "error": {
    "type": "server_error",
    "code": "server_error",
    "message": "the voice service is temporarily unavailable, please retry"
  }
}
```

## What to handle

| Situation | What happens | What to do |
|---|---|---|
| Invalid or missing key | `error` then close `4001` | Check the key / token. |
| Out of credits | `error` then close `4003` | Add credits, then reconnect. |
| Too many concurrent calls | `error` then close `4008` | You've hit your plan's limit — close another session or upgrade. |
| Service busy or unavailable | `error` asking you to retry | Reconnect after a short backoff. |
| Bad message | `error`, connection stays open | Fix the offending event and continue. |

## Reconnecting

For `1013` (busy) and transient `server_error`s, reconnect with a short
**exponential backoff** (e.g. 0.5s, 1s, 2s, capped). Start a fresh session and
re-send your `session.update` configuration on the new connection.

For `4001`, `4003`, and `4008`, don't blindly retry — fix the cause first (the
key, your balance, or the number of open sessions).

> **Note.** Error messages are deliberately generic and safe to surface or log;
> the details you need for debugging are the `code` and the close code.
