---
title: "Errors"
description: "Errors"
---

Every refusal has one shape, on every surface:

```json
{
  "error": {
    "code": "conflict",
    "message": "Someone saved this file first. Read it again, redo your change on the new version and save.",
    "retryable": true,
    "currentVersion": 4
  }
}
```

- **Where it appears.** In a tool result with `isError: true`, as the text of the result; in the `data` of a JSON-RPC error, so `error.data.error` holds it and the JSON-RPC `error.code` stays numeric; and as the body of an upload or download link answer, with the HTTP status that goes with the code.
- **`code`.** Lower snake_case, such as `invalid_arguments`, `unknown_tool`, `organization_inactive`, `rate_limited`, `credits_exhausted` or `internal`. Branch on `code`; the set is fixed.
- **`message`.** One plain sentence in the language of the request, ending with the next step. It never starts with the code.
- **`retryable`.** Always `true` or `false`. When `true`, repeat the call, after `retryAfterSeconds` when it is present.
- **Details.** Next to the three fields, a refusal may carry `currentVersion` (the version to redo your change on), `retryAfterSeconds`, `failingRecords` (the records that failed, in a batch) and `issues` (each invalid field and what it expects).

A failure Siglata did not expect answers `internal`, retryable, with a generic message: it never carries database, provider or stack text.
