# Errors

Errors are RFC 9457 problem details, served as `application/problem+json`. Branch on `code`, which is stable within a version. Show `detail` to people; it is written for them.

```json
{
  "type": "https://docs.acquestor.com/problems/deal_access_off",
  "title": "Not allowed",
  "status": 403,
  "code": "deal_access_off",
  "detail": "Outside AI access is off for your deals. Turn it on for one deal on acquestor.com and pick this client.",
  "instance": "…"
}
```

| Field | Meaning |
| --- | --- |
| `type` | A page on this site that explains the code |
| `title` | The HTTP status in words |
| `status` | The HTTP status |
| `code` | The stable error code |
| `detail` | What went wrong and what to do, in plain words |
| `instance` | The request path |
| `missing` | For `missing_input`, the fields to send |
| `price`, `balance` | For 402s |

Every error response carries `Acquestor-Credits-Charged: 0`. An error never charges.

On the MCP server, an error comes back as a tool result with `isError: true`. Its text is `detail`, plus "Nothing ran and nothing was charged." on a 402, and the problem object is in `structuredContent`. A call missing a required argument fails the tool's input schema before it runs, and the error names the field:

```json
"missing_input: The call needs capex_reserve; Acquestor never fills a required input with a default it can't source. Missing: capex_reserve. Retrying the same call unchanged will fail the same way. Request ID req_90b048ce0c7a4c60b6dffbf242a06f4b."
```

## Codes

| Code | Status | Meaning |
| --- | --- | --- |
| [`missing_input`](/problems/missing_input) | 422 | A required input is missing |
| [`invalid_input`](/problems/invalid_input) | 422 | An input is out of range or the wrong type |
| [`invalid_json`](/problems/invalid_json) | 400 | The body isn't valid JSON |
| [`unsupported_media_type`](/problems/unsupported_media_type) | 415 | Unsupported content type |
| [`invalid_header`](/problems/invalid_header) | 400 | A header has an invalid value |
| [`unauthorized`](/problems/unauthorized) | 401 | Sign-in required |
| [`insufficient_scope`](/problems/insufficient_scope) | 403 | The key lacks a scope |
| [`forbidden_role`](/problems/forbidden_role) | 403 | Your role can't do this |
| [`interface_only`](/problems/interface_only) | 403 | Only acquestor.com can do this |
| [`deal_access_off`](/problems/deal_access_off) | 403 | This client has no grant for this deal |
| [`beta_terms_unavailable`](/problems/beta_terms_unavailable) | 403 | The beta agreement isn't published yet |
| [`beta_terms_not_accepted`](/problems/beta_terms_not_accepted) | 403 | Accept the beta agreement first |
| [`licence_unavailable`](/problems/licence_unavailable) | 403 | The listing licence isn't published yet |
| [`licence_not_accepted`](/problems/licence_not_accepted) | 403 | Accept the current listing licence |
| [`terms_unavailable`](/problems/terms_unavailable) | 403 | Contribution terms aren't published yet |
| [`invite_required`](/problems/invite_required) | 403 | The beta is invite-only |
| [`fresh_sign_in_required`](/problems/fresh_sign_in_required) | 403 | Sign in again |
| [`cross_origin`](/problems/cross_origin) | 403 | Cross-site request refused |
| [`account_deleted`](/problems/account_deleted) | 403 | This account was deleted |
| [`not_found`](/problems/not_found) | 404 | Not found |
| [`method_not_allowed`](/problems/method_not_allowed) | 405 | Method not allowed |
| [`already_sent`](/problems/already_sent) | 409 | The inquiry was already sent |
| [`already_attested`](/problems/already_attested) | 409 | Already attested |
| [`idempotency_in_progress`](/problems/idempotency_in_progress) | 409 | The same request is still running |
| [`invite_stopped`](/problems/invite_stopped) | 409 | That address asked not to receive invitations |
| [`email_failed`](/problems/email_failed) | 502 | The email couldn't be sent |
| [`invitations_unavailable`](/problems/invitations_unavailable) | 503 | Invitations are off |
| [`idempotency_key_reused`](/problems/idempotency_key_reused) | 422 | Idempotency-Key used for a different call |
| [`marketplace_printout`](/problems/marketplace_printout) | 422 | This looks like a marketplace printout |
| [`not_yet_supported`](/problems/not_yet_supported) | 422 | Not built yet |
| [`file_too_large`](/problems/file_too_large) | 413 | File too large |
| [`invalid_cursor`](/problems/invalid_cursor) | 400 | That cursor isn't from this list |
| [`quota_exhausted`](/problems/quota_exhausted) | 429 | A quota is used up until it resets |
| [`rate_limited`](/problems/rate_limited) | 429 | Too many requests |
| [`insufficient_credits`](/problems/insufficient_credits) | 402 | Not enough credits |
| [`over_max_credits`](/problems/over_max_credits) | 402 | Over your Acquestor-Max-Credits |
| [`over_limit`](/problems/over_limit) | 402 | Monthly limit reached |
| [`not_configured`](/problems/not_configured) | 503 | Not available on this server |
| [`internal_error`](/problems/internal_error) | 500 | Something went wrong on our side |
| [`auth_not_configured`](/problems/auth_not_configured) | 500 | Sign-in isn't configured |
| [`use_hosted_sign_in`](/problems/use_hosted_sign_in) | 400 | Use the sign-in page |
| [`link_expired`](/problems/link_expired) | 400 | The sign-in link expired |
| [`invalid_callback`](/problems/invalid_callback) | 400 | The sign-in link is incomplete |
| [`state_mismatch`](/problems/state_mismatch) | 400 | The sign-in attempt expired |
