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

# Errors

> Reference Herm API error response bodies, HTTP status codes, validation failures, authentication problems, and common recovery steps.

API errors return a JSON body with an `error` code and a human-readable
`message`. Treat the HTTP status and `error` as the machine-readable contract.
Terminal errors may also include `"retryable": false`; do not resubmit the
same request when that field is present.

## Error format

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "error_code",
  "message": "Human-readable description of what went wrong"
}
```

## Error codes

| HTTP Status | Error Code             | Description                                                                                                                          |
| ----------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 400         | `validation_error`     | The request body or parameters are invalid                                                                                           |
| 401         | `unauthorized`         | The API key is missing, invalid, or revoked                                                                                          |
| 403         | `forbidden`            | The authenticated caller cannot perform the operation                                                                                |
| 404         | `not_found`            | The requested resource does not exist in the authenticated organization                                                              |
| 409         | `conflict`             | An optimistic concurrency check failed                                                                                               |
| 409         | `invalid_state`        | The session state does not allow the operation — e.g. a busy request mixes prompt and control events, or archiving a running session |
| 409         | `no_active_turn`       | The session has no live turn for a steer or interrupt control event                                                                  |
| 410         | `response_expired`     | The turn that requested an approval, clarification, or synchronous custom-tool result has ended; do not retry the same response      |
| 429         | `rate_limited`         | Too many requests — back off and retry                                                                                               |
| 500         | `server_error`         | An unexpected error occurred on the server                                                                                           |
| 502         | `server_error`         | An upstream credential or connector operation failed; retry only when the operation is safe to repeat                                |
| 502         | `hermes_delete_failed` | Herm could not delete the session from the runtime; retry the session deletion                                                       |
| 503         | `server_error`         | A required service is temporarily unavailable; retry with exponential backoff                                                        |

Interpret `server_error` together with its HTTP status. A `500` is an unexpected
internal failure, a `502` identifies an upstream operation failure, and a `503`
is explicitly temporary and retryable.

## Validation errors

`400 validation_error` messages name the failing field path and the violated
constraint, one `path: constraint` entry per issue, separated by `;`. The
offending value is never echoed back.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "validation_error",
  "message": "events[0].content[0].text: Expected a string at most 20000 character(s) long"
}
```

## Common scenarios

### Missing API key

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://api.herm.run/v1/agents"
```

Returns `401 unauthorized` with `Invalid or missing API key`.

### Agent version conflict

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "conflict",
  "message": "Agent changed from version 2 to 3"
}
```

Fetch the agent again and retry the full update body with the latest
`expectedVersion`.

### File already exists

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "conflict",
  "message": "Path reports/q3.md already exists"
}
```

Retry with `overwrite: true`, or choose a different path.

### File or directory not found

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "not_found",
  "message": "Path reports/missing.md was not found"
}
```

List the workspace with the [Files API](/api-reference/files) before reading or
deleting a path.

### Turn already in progress

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "invalid_state",
  "message": "A turn is already in progress"
}
```

A session runs one turn at a time. Prompt-only requests are queued automatically;
this error means the request contains events that cannot be queued together.
Send prompt and control events separately — see
[Queue a message while a turn is running](/api-reference/send-message#queue-a-message-while-a-turn-is-running).

### Rate limits

Per-agent user limits return a structured `429` response:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": "rate_limited",
  "message": "Message limit reached.",
  "rateLimit": {
    "resource": "messages",
    "limit": 100,
    "remaining": 0,
    "periodSeconds": 60,
    "resetAfterSeconds": 17
  }
}
```

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
HTTP/1.1 429 Too Many Requests
Retry-After: 17
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 17
```

`resource` is `conversations` or `messages`. Wait at least the integer number of
seconds in `Retry-After` before retrying. Handle `rate_limited` explicitly in
your client.

Successful operations include `RateLimit-Limit`, `RateLimit-Remaining`, and
`RateLimit-Reset`. See
[Rate limits](/api-reference/rate-limits) for configuration and counting
behavior.

### Agent not found

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "error": "not_found", "message": "Agent not found" }
```
