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

# Error codes

> The request-error surface (auth, validation, limits) and where to resolve refusal reasons.

There are two kinds of "something is wrong," and they are handled differently.

* A **refused value** is a successful `200` containing `{ "unavailable": "..." }`. It is a product fact — never an error, never retry it. See below.
* A **request error** is a non-2xx HTTP status. The table is the whole surface.

## Request errors

| HTTP | Code                                    | Retry?      | What to do                                                                                                               |
| ---- | --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
| 401  | `missing_api_key`                       | No          | Add the `X-API-Key` header.                                                                                              |
| 401  | `invalid_api_key`                       | No          | The key is unknown or revoked — fix or reissue it.                                                                       |
| 404  | `no_match` or endpoint-specific refusal | No          | The symbol or requested inventory item was not found. The body is the same flat refusal envelope as other tool refusals. |
| 413  | `request_too_large`                     | No          | The JSON body exceeded the 64 KiB request cap or nesting guard. Shrink the body.                                         |
| 422  | validation error / `invalid_request`    | No          | Schema 1 returns FastAPI `detail`; schema 2 returns a typed `invalid_request` envelope with `errors[]`.                  |
| 429  | `rate_limit_exceeded`                   | Yes         | Per-minute rate exceeded — back off a few seconds.                                                                       |
| 429  | `quota_exhausted`                       | After reset | Daily/monthly quota used up — wait for the window to reset.                                                              |
| 5xx  | —                                       | Yes         | Transient server/upstream issue — retry with backoff.                                                                    |

HTTP refusals are not wrapped in `{ "error": ... }`. Schema-2 failures use typed envelopes; legacy schema-1 requests can still use the frozen flat value-refusal shape:

```json title="HTTP 413" theme={null}
{ "available": false, "reason": "request_too_large" }
```

Schema 1 validation errors follow FastAPI's validation shape, so you can log exactly which field was wrong:

```json title="HTTP 422" theme={null}
{
  "detail": [
    { "loc": ["body", "periods"], "msg": "Input should be less than or equal to 20", "type": "less_than_equal" }
  ]
}
```

Schema 2 validation errors use the schema-2 envelope:

```json title="Schema 2 HTTP 422" theme={null}
{
  "data": {
    "unavailable": "invalid_request",
    "recovery": { "action": "none", "note": "correct the params named in errors and resubmit" },
    "errors": [{ "param": "periods", "given": 99, "expected": "Input should be less than or equal to 20" }]
  },
  "meta": { "schema_version": "2" }
}
```

See [Errors and retries](/docs/guides/errors-and-retries) for a retry loop, and [Plans and limits](/docs/reference/plans-and-limits) for the two `429` windows.

## Refusal reasons

Refusals are not in the table above — they live inside a `200` and are enumerated by the API itself. Fetch the catalog at runtime instead of hard-coding:

```json title="stock_reference catalog=refusal_tokens (trimmed)" theme={null}
{
  "catalog": "refusal_tokens",
  "items": [
    { "code": "AMBIGUOUS_CANDIDATE", "public": "ambiguous_candidate",
      "recovery_action": "use_full_document",
      "note": "Fact-level candidates survived extraction guards but no single number was provable; inspect the filing when an accession is provided." },
    { "code": "CASH_RETURN_UNAVAILABLE", "public": "cash_return_unavailable",
      "recovery_action": "use_full_document",
      "note": "A cash-return operand is not a genuinely-tagged value; serving 0 would be a wrong number, so the yield refuses honestly instead." },
    { "code": "NOT_APPLICABLE_FOR_SHAPE", "public": "not_applicable_for_shape",
      "recovery_action": "use_alternative_field",
      "note": "The statement shape structurally lacks this line; use the named shape-native analog when provided." }
  ]
}
```

Each entry maps a refusal token to a recovery action and a human note. Common field-level reasons include `not_reported` (the concept was not tagged in the filing), `not_applicable_for_shape` (the statement shape structurally lacks that line), and `cash_return_unavailable`; tool-level reasons include `no_match`, `no_insider_filings`, and `no_tracked_holders`.
