# Errors

Updated 2026-10-12.

Every error is JSON: `{"error":{"code","message","next","docs"}}`, where `docs` links here (`https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#<code>`). Errors are never charged: a 4xx or 5xx is never settled.

| Code | HTTP | What it means | What to do |
|---|---|---|---|
| [payment_required](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_required) | 402 | The route is paid and the request carries no PAYMENT-SIGNATURE header. The body and the PAYMENT-REQUIRED header (base64) hold the x402 offer; it is sent before the input is read, on GET and POST. | Pay accepts[0] with an x402 v2 client and retry the same request with PAYMENT-SIGNATURE. |
| [payment_invalid](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_invalid) | 402 | PAYMENT-SIGNATURE could not be decoded, or the payment is not x402 v2 exact, or its signature is refused. | Build a new payment from the 402 offer. |
| [payment_replayed](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_replayed) | 402 | This payment (its nonce) was already used. | Sign a new payment. To get a paid answer again, send the same payment-identifier with the same payment. |
| [payment_underpaid](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_underpaid) | 402 | The payment amount is below the route price. | Pay at least accepts[0].amount (atomic USDC, 6 decimals). |
| [payment_expired](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_expired) | 402 | The payment is outside its time window: validBefore is less than 5 seconds away or past, or validAfter is still ahead. | Sign a new payment with a current time window. |
| [payment_wrong_network](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_wrong_network) | 402 | The payment is not on Base, network eip155:8453. | Pay on the network named in accepts[0].network. |
| [payment_wrong_asset](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_wrong_asset) | 402 | The payment is not in USDC at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. | Pay in the asset named in accepts[0].asset. |
| [payment_wrong_payto](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_wrong_payto) | 402 | The payment is to another address than ours. | Pay to accepts[0].payTo. |
| [payment_wrong_resource](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_wrong_resource) | 402 | The payment names another URL than the one called (or none). | Sign the payment for resource.url of this 402. |
| [facilitator_unavailable](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#facilitator_unavailable) | 503 | The x402 facilitator could not verify or settle the payment. Nothing was charged. | Retry later with a new payment. |
| [settlement_unknown](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#settlement_unknown) | 503 | Settlement did not confirm and may still have completed. The payment is held for reconciliation. | Retry with the SAME PAYMENT-SIGNATURE (never a new one); it is never charged twice. Retry within about 20 s (the 60 s signing window less the 10 s settle timeout and the 30 s Retry-After); after that the retry is refused as expired and the payment stays held for reconciliation. |
| [payment_in_progress](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_in_progress) | 409 | A request with the same payment-identifier is still being processed. | Retry in a few seconds with the same request. |
| [rate_limited](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#rate_limited) | 429 | Too many refused payments from this payer address or client IP (5 in 10 minutes). Not charged. | Wait for the Retry-After header, then send a correctly signed payment. |
| [bad_request](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#bad_request) | 400 | The input is not valid (see message). | Check the input schema in /openapi.json; GET /v1/validate checks an id for free. |
| [unknown_id](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#unknown_id) | 404 | The id is not in the dataset (for a batch: none of the items is). Not charged. For an unknown product on GET /v1/eol/{product} and /v1/eol/{product}/{cycle}, error.suggestions lists up to 5 closest product ids (empty if none is close). On GET /v1/eol/image: no part of the image (repository, runtime or base OS in the tag) matched a product and cycle. | Retry with a suggested id; GET /v1/eol/index or /v1/models/index lists valid ids (free). |
| [too_many_items](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#too_many_items) | 413 | The batch is over the limit: 50 items for /v1/eol/check, 100 CVEs for /v1/kev/check, 50 items, 50 packages and 100 CVEs for /v1/stack/check and /v1/stack/watch, 50 purls for /v1/osv/check; on /v1/stack/watch also a watch token over 32,000 characters at the start or 48,000 on a re-check. Not charged. | Split the batch (a watch: start two smaller watches). |
| [snapshot_expired](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#snapshot_expired) | 410 | The since snapshot_id is unknown or no longer kept, so no change list can be built. Not charged. | Download the full snapshot (/v1/{dataset}/snapshot) and use its snapshot_id as the next since. |
| [paused](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#paused) | 503 | Paid routes are temporarily paused. | Retry after the Retry-After header; free routes still answer. |
| [stale_data](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#stale_data) | 503 | The dataset was not refreshed within twice its cadence, so paid routes do not answer. | GET /health shows each dataset; retry later. |
| [payer_blocked](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payer_blocked) | 403 | The paying address is blocked by sanctions screening. Not settled. | None. |
| [l402_invalid](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#l402_invalid) | 401 | The Authorization: L402 credential failed a check (macaroon signature, a caveat, expiry or preimage) or its preimage was already used. Only sent when the L402 rail is on. | Pay the invoice in the WWW-Authenticate header and retry with the new macaroon and preimage. |
| [internal](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#internal) | 500 | An unexpected server error. Not charged. | Retry later. |
| [dataset_unavailable](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#dataset_unavailable) | 503 | No snapshot of the dataset is loaded yet. | GET /health shows each dataset; retry later. |
| [payments_unconfigured](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payments_unconfigured) | 503 | Payments are not available on this server. | Use the free routes; retry later. |
| [payment_id_conflict](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#payment_id_conflict) | 409 | The payment-identifier id was already used with a different payment or request. | Use a new payment-identifier id for a new payment. |
| [no_match](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#no_match) | 404 | No record meets the search (POST /v1/models/cheapest). Not charged. | Loosen the constraints. |
| [not_implemented](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#not_implemented) | 501 | This priced route is not available yet. A payment for it is never settled. | Use another route. |
| [token_invalid](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#token_invalid) | 400 | The watch token for POST /v1/stack/watch is not one we issued (its shape, signature or contents are wrong). Not charged. | Start a new watch: POST /v1/stack/watch with the stack. |
| [token_expired](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#token_expired) | 410 | The watch token for POST /v1/stack/watch is past its expires_at (180 days), or in a format no longer read. Not charged. | Start a new watch: POST /v1/stack/watch with the stack (it is in watch.stack of your last answer). |
| [watch_unavailable](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#watch_unavailable) | 503 | Stack watch is not available on this server. Not charged. | Use POST /v1/stack/check (no token). |
| [not_found](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#not_found) | 404 | No route at this path. | GET /llms.txt lists every route (free). |
| [method_not_allowed](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#method_not_allowed) | 405 | The path exists but not for this method. | Use a method from the Allow header. |
| [body_too_large](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#body_too_large) | 413 | The request body is over 64 KB. | Send a smaller body (split a batch). |
| [headers_too_large](https://g5joilnmeep4ntz3nwezxt5dmu.srv.us/docs/errors#headers_too_large) | 431 | The request headers are too large. | Send smaller headers. |

### payment_required

HTTP 402. The route is paid and the request carries no PAYMENT-SIGNATURE header. The body and the PAYMENT-REQUIRED header (base64) hold the x402 offer; it is sent before the input is read, on GET and POST. Next: Pay accepts[0] with an x402 v2 client and retry the same request with PAYMENT-SIGNATURE.

### payment_invalid

HTTP 402. PAYMENT-SIGNATURE could not be decoded, or the payment is not x402 v2 exact, or its signature is refused. Next: Build a new payment from the 402 offer.

### payment_replayed

HTTP 402. This payment (its nonce) was already used. Next: Sign a new payment. To get a paid answer again, send the same payment-identifier with the same payment.

### payment_underpaid

HTTP 402. The payment amount is below the route price. Next: Pay at least accepts[0].amount (atomic USDC, 6 decimals).

### payment_expired

HTTP 402. The payment is outside its time window: validBefore is less than 5 seconds away or past, or validAfter is still ahead. Next: Sign a new payment with a current time window.

### payment_wrong_network

HTTP 402. The payment is not on Base, network eip155:8453. Next: Pay on the network named in accepts[0].network.

### payment_wrong_asset

HTTP 402. The payment is not in USDC at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. Next: Pay in the asset named in accepts[0].asset.

### payment_wrong_payto

HTTP 402. The payment is to another address than ours. Next: Pay to accepts[0].payTo.

### payment_wrong_resource

HTTP 402. The payment names another URL than the one called (or none). Next: Sign the payment for resource.url of this 402.

### facilitator_unavailable

HTTP 503. The x402 facilitator could not verify or settle the payment. Nothing was charged. Next: Retry later with a new payment.

### settlement_unknown

HTTP 503. Settlement did not confirm and may still have completed. The payment is held for reconciliation. Next: Retry with the SAME PAYMENT-SIGNATURE (never a new one); it is never charged twice. Retry within about 20 s (the 60 s signing window less the 10 s settle timeout and the 30 s Retry-After); after that the retry is refused as expired and the payment stays held for reconciliation.

### payment_in_progress

HTTP 409. A request with the same payment-identifier is still being processed. Next: Retry in a few seconds with the same request.

### rate_limited

HTTP 429. Too many refused payments from this payer address or client IP (5 in 10 minutes). Not charged. Next: Wait for the Retry-After header, then send a correctly signed payment.

### bad_request

HTTP 400. The input is not valid (see message). Next: Check the input schema in /openapi.json; GET /v1/validate checks an id for free.

### unknown_id

HTTP 404. The id is not in the dataset (for a batch: none of the items is). Not charged. For an unknown product on GET /v1/eol/{product} and /v1/eol/{product}/{cycle}, error.suggestions lists up to 5 closest product ids (empty if none is close). On GET /v1/eol/image: no part of the image (repository, runtime or base OS in the tag) matched a product and cycle. Next: Retry with a suggested id; GET /v1/eol/index or /v1/models/index lists valid ids (free).

### too_many_items

HTTP 413. The batch is over the limit: 50 items for /v1/eol/check, 100 CVEs for /v1/kev/check, 50 items, 50 packages and 100 CVEs for /v1/stack/check and /v1/stack/watch, 50 purls for /v1/osv/check; on /v1/stack/watch also a watch token over 32,000 characters at the start or 48,000 on a re-check. Not charged. Next: Split the batch (a watch: start two smaller watches).

### snapshot_expired

HTTP 410. The since snapshot_id is unknown or no longer kept, so no change list can be built. Not charged. Next: Download the full snapshot (/v1/{dataset}/snapshot) and use its snapshot_id as the next since.

### paused

HTTP 503. Paid routes are temporarily paused. Next: Retry after the Retry-After header; free routes still answer.

### stale_data

HTTP 503. The dataset was not refreshed within twice its cadence, so paid routes do not answer. Next: GET /health shows each dataset; retry later.

### payer_blocked

HTTP 403. The paying address is blocked by sanctions screening. Not settled. Next: None.

### l402_invalid

HTTP 401. The Authorization: L402 credential failed a check (macaroon signature, a caveat, expiry or preimage) or its preimage was already used. Only sent when the L402 rail is on. Next: Pay the invoice in the WWW-Authenticate header and retry with the new macaroon and preimage.

### internal

HTTP 500. An unexpected server error. Not charged. Next: Retry later.

### dataset_unavailable

HTTP 503. No snapshot of the dataset is loaded yet. Next: GET /health shows each dataset; retry later.

### payments_unconfigured

HTTP 503. Payments are not available on this server. Next: Use the free routes; retry later.

### payment_id_conflict

HTTP 409. The payment-identifier id was already used with a different payment or request. Next: Use a new payment-identifier id for a new payment.

### no_match

HTTP 404. No record meets the search (POST /v1/models/cheapest). Not charged. Next: Loosen the constraints.

### not_implemented

HTTP 501. This priced route is not available yet. A payment for it is never settled. Next: Use another route.

### token_invalid

HTTP 400. The watch token for POST /v1/stack/watch is not one we issued (its shape, signature or contents are wrong). Not charged. Next: Start a new watch: POST /v1/stack/watch with the stack.

### token_expired

HTTP 410. The watch token for POST /v1/stack/watch is past its expires_at (180 days), or in a format no longer read. Not charged. Next: Start a new watch: POST /v1/stack/watch with the stack (it is in watch.stack of your last answer).

### watch_unavailable

HTTP 503. Stack watch is not available on this server. Not charged. Next: Use POST /v1/stack/check (no token).

### not_found

HTTP 404. No route at this path. Next: GET /llms.txt lists every route (free).

### method_not_allowed

HTTP 405. The path exists but not for this method. Next: Use a method from the Allow header.

### body_too_large

HTTP 413. The request body is over 64 KB. Next: Send a smaller body (split a batch).

### headers_too_large

HTTP 431. The request headers are too large. Next: Send smaller headers.
