# Errors and refusals

Every refusal is one envelope: status refused, refusal.code, a message, recover_with (the way out).

| code | means | way out |
|---|---|---|
| BAKED_TOOL_REQUIRED | The question has a typed tool that carries rules raw SQL gets wrong (one payment basis per median, floors, cut points). | Call the tool named in recover_with with the arguments it shows. |
| RAW_SQL_REQUIRED | No typed tool answers this; the raw door does. | Re-ask through query_substrate with the SQL in recover_with. |
| VINTAGE_REQUIRED | The table is annual or versioned and the question did not pin a year or version. | Add the year, quarter or version_id recover_with names. |
| REQUIRED_FILTER_MISSING | The table needs a filter before it can be read within budget (a state on hospital prices, a contract on Stars). | Add the filter recover_with names and re-issue. |
| AMBIGUOUS_ENTITY | A name matched more than one thing, or nothing we serve. | Use one of the accepted names in the message, or resolve_entity / resolve_provider first. |
| UNSAFE_JOIN | The join would blend grains or bases that must stay apart. | Join through the key how_to_join names, or ask for each side separately. |
| NO_COVERAGE | We do not hold what was asked for: the payer is not indexed, the tool is withdrawn, the year is outside the files. | recover_with names the nearest thing we do hold. This is an absence we can prove, never a zero. |
| NO_DATA | The question was understood and the filters matched nothing. | Widen one filter at a time; the answer names what was searched. |
| METHOD_MISMATCH | The request would compare two payment bases (per diem with fee schedule, percent of charges with a dollar). | Pick one basis; compare_hospital_rates segments them for you. |
| SCAN_LIMIT_EXCEEDED | The query would scan more than the budget allows, or ran past the 40 s synchronous window. | Narrow the predicate (one state, one code, one year), aggregate in SQL, or use the async lane on a paid plan. |
| SUPPRESSED | The source suppresses this cell (CMS prints * for 10 or fewer). | Ask at a coarser grain; the bounds are in the answer. |
| QUARANTINED_METHOD | The tool is quarantined by the live audit for a measured defect and will not execute. | recover_with names the tool that serves the same purpose. |
| INVALID_ARGUMENTS | The arguments did not match the tool's input model. | fields says what each one accepts and recover_with carries a corrected example. HTTP 400 on REST. |
| DATA_ALLOWANCE_REACHED | This account has been delivered its monthly data allowance. | detail.resets_on says when; ask for the aggregate rather than the rows. HTTP 429 on REST. |
| PLAN_REQUIRED | This account's plan does not include the door asked for (the async lane, paging). | detail.upgrade_url; the sync door still answers questions. HTTP 402 on REST. |

| HTTP | codes | means |
|---|---|---|
| 401 | unauthenticated / invalid_key | Missing, empty or unrecognised bearer key. |
| 403 | entitlement_denied / scope_forbidden | The key may not call this tool. |
| 404 | unknown_tool | No tool of that name on this door. |
| 400 | INVALID_ARGUMENTS, invalid_input | The body did not match the tool's input model. |
| 402 | PLAN_REQUIRED | The plan does not include this door. |
| 422 | every other charter refusal | Understood and declined, with recover_with. |
| 429 | DATA_ALLOWANCE_REACHED, rate_limit_exceeded | The monthly allowance or the per-second rate limit. |
| 500 | TOOL_FAILED, ENGINE_* | Our failure; the correlation id in the answer is what we read. |
