# Error codes and cost reporting
Every refused or failed tool call says why with a stable **code** and a **retry hint**, and every tool result says what it cost. Agents can branch on the code instead of parsing English.
## How an error looks
A tool result that is JSON keeps its `error` field and gains `error_info`:
```json
{
"error": "pull_ceiling_exceeded",
"message": "This account has reached its fair-use cap ...",
"error_info": {
"code": "pull_ceiling_exceeded",
"message": "This account has reached its fair-use cap ...",
"retryable": false,
"retry_after_s": null,
"docs": "https://justclaw-it.com/docs/errors#pull_ceiling_exceeded",
"legacy_error_until": "2027-02-03"
}
}
```
Refusals that arrive as plain text (quota and keyless limits, answered before the tool runs) carry the same code in the result's `_meta["com.justclaw-it/call"].error_code`.
A refusal is still a normal tool result (`isError` is false, as before): check for `error` / `error_info` in the JSON. `isError` is true only when the tool itself failed unexpectedly (`internal_error`).
Treat a code you don't know like `internal_error` and follow its `retry_after_s`. A `null` `retry_after_s` means retrying the same call will not help.
## Compatibility (90 days)
The old `error` values stay exactly as they were until **2027-02-03**. After that date `error` holds the stable code itself. Most errors already do; the changes are `not available` → `not_available`, `not found` → `not_found`, `unknown tool …` → `unknown_tool`, and free-text argument errors → `invalid_argument` (the text moves to `error_info.message`). Read `error_info.code` today and nothing changes for you.
## Cost reporting
Every tool result carries `_meta["com.justclaw-it/call"]`:
| field | meaning |
| --- | --- |
| `request_id` | id of this call, also sent as the `X-Request-ID` response header; quote it to support |
| `credits_charged` | credits this call took (0 for free tools) |
| `credits_refunded` | credits given back because the call was refused or found nothing |
| `balance` | the account's spendable credits after this call (keyed and signed-in callers) |
JSON-RPC batch requests (several messages in one POST) are refused with `batch_not_supported` before anything is charged; send one message per request.
## Account and plan
#### `key_required`
This tool needs an API key (free, no card). Keyless use covers search_components only. Retrying the same call won't help: fix the call, change plan or wait.
#### `pro_required`
This tool or option is part of the Pro plan. Retrying the same call won't help: fix the call, change plan or wait.
#### `out_of_credits`
No credits left for this period. Wait for the refill or upgrade. Retry after the next credit refill (or upgrade).
#### `ip_daily_free_cap`
The free plan's daily credit cap for your network is used up. Retry after 00:00 UTC (`retry_after_s` counts down to it).
#### `revoked`
This API key was revoked. Create a new one on /account. Retrying the same call won't help: fix the call, change plan or wait.
## Rate limits and caps
#### `search_rate_limited`
Too many free discovery calls in the last minute. Retry after 60 seconds.
#### `search_daily_cap`
Daily free discovery limit reached for this key or network. Retry after 00:00 UTC (`retry_after_s` counts down to it).
#### `too_many_requests`
Too many requests from your network. Retry after 60 seconds.
#### `unavailable_pulls_rate_limited`
Too many get_component calls for ids that are not available. Retry after 60 seconds.
#### `pull_ceiling_exceeded`
Fair-use cap on distinct components pulled in 12 months reached. Retrying the same call won't help: fix the call, change plan or wait.
#### `daily_limit`
Daily limit for this tool reached. Retry after 00:00 UTC (`retry_after_s` counts down to it).
#### `build_limit`
Daily build limit reached. Retry after 00:00 UTC (`retry_after_s` counts down to it).
#### `daily_ai_budget`
The service's daily AI budget for this tool is used up. Retry after 00:00 UTC (`retry_after_s` counts down to it).
#### `report_daily_limit`
Daily licence report limit for this account reached. Retry after 00:00 UTC (`retry_after_s` counts down to it).
## Problems with the request
#### `not_available`
No component with that id is available (missing, or not licence-cleared). Retrying the same call won't help: fix the call, change plan or wait.
#### `not_found`
Nothing found for that id. Retrying the same call won't help: fix the call, change plan or wait.
#### `invalid_argument`
An argument has a value the tool does not accept; the message says which. Retrying the same call won't help: fix the call, change plan or wait.
#### `bad_request`
The request is malformed. Retrying the same call won't help: fix the call, change plan or wait.
#### `bad_prompt`
The prompt was empty or not usable. Retrying the same call won't help: fix the call, change plan or wait.
#### `too_many`
Too many items in one call; split it. Retrying the same call won't help: fix the call, change plan or wait.
#### `nothing_to_check`
The call named nothing to check. Retrying the same call won't help: fix the call, change plan or wait.
#### `no_components`
No components matched; nothing was built (refunded). Retrying the same call won't help: fix the call, change plan or wait.
#### `unknown_tool`
No tool with that name. Retrying the same call won't help: fix the call, change plan or wait.
#### `batch_not_supported`
JSON-RPC batch requests are not supported; send one message per POST. Retrying the same call won't help: fix the call, change plan or wait.
#### `feature_not_enabled`
This feature is not enabled for this account yet. Retrying the same call won't help: fix the call, change plan or wait.
#### `file_too_large`
An uploaded file is larger than the limit; send a smaller file. Retrying the same call won't help: fix the call, change plan or wait.
#### `too_many_files`
Too many files in one report. Retrying the same call won't help: fix the call, change plan or wait.
#### `too_many_packages`
The files list more packages than one report allows; split them. Retrying the same call won't help: fix the call, change plan or wait.
#### `unsupported_lockfile`
That file type is not supported; the message lists the supported ones. Retrying the same call won't help: fix the call, change plan or wait.
#### `parse_failed`
The file could not be parsed (refunded). Retrying the same call won't help: fix the call, change plan or wait.
#### `parse_timeout`
Parsing took too long; send a smaller file (refunded). Retrying the same call won't help: fix the call, change plan or wait.
#### `empty_report`
No packages were found in the files (refunded). Retrying the same call won't help: fix the call, change plan or wait.
## Temporary service problems
#### `registry_busy`
The registry is busy; retry shortly. Retry after 5 seconds.
#### `builder_unavailable`
The builder is temporarily unavailable. Retry after 30 seconds.
#### `adapt_failed`
Adapting the components failed; retry or change the prompt. Retry after 30 seconds.
#### `worker_response_too_large`
The result was too large to return. Retrying the same call won't help: fix the call, change plan or wait.
#### `lost`
The build result expired or was lost; start a new build. Retrying the same call won't help: fix the call, change plan or wait.
#### `internal_error`
Unexpected server error. Retry once; if it repeats, contact support with the request_id. Retry after 5 seconds.