---
title: Errors & troubleshooting
description: CrossModel OpenAI- and Anthropic-compatible error shapes, common codes, and how to debug.
---

# Errors & troubleshooting

CrossModel returns errors in the format that matches the protocol you called. OpenAI-compatible endpoints return OpenAI-style error objects; the Anthropic Messages endpoint returns Anthropic-style error objects.

## OpenAI-compatible error format

```json
{
  "error": {
    "message": "Missing Bearer token in Authorization header.",
    "type": "authentication_error",
    "param": null,
    "code": "missing_api_key"
  }
}
```

| Field | Notes |
|------|------|
| `message` | A human-readable description. |
| `type` | The broad error category. |
| `param` | The offending field, or `null` when there isn't a specific one. |
| `code` | A stable error code — prefer branching on this in code. |

## Anthropic-compatible error format

```json
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Missing API key."
  }
}
```

The Anthropic format doesn't include a `code` field. Branch on the HTTP status code and `error.type`.

## Common errors

| HTTP status | OpenAI `type` | Common `code` | Notes |
|------------|---------------|-------------|------|
| `400` | `invalid_request_error` | `invalid_json`, `invalid_messages`, `unsupported_parameter`, `unsupported_responses_feature` | Malformed body or parameters. |
| `401` | `authentication_error` | `missing_api_key`, `invalid_api_key`, `api_key_inactive`, `user_inactive` | Key missing, wrong, disabled, or account unavailable. |
| `402` | `billing_error` | `insufficient_balance`, `no_wallet` | Out of balance or no wallet on the account. |
| `404` | `invalid_request_error` | `model_not_found` | Model doesn't exist, isn't listed, or is currently unavailable. |
| `429` | `rate_limit_error` | `rate_limit_exceeded` | Over the API key's RPM or TPM limit. |
| `502` | `provider_error` | `provider_error` | The model service couldn't complete the request. |
| `503` | `api_error` | `model_unavailable` | Model temporarily unavailable — retry shortly. |
| `500` | `api_error` | `internal_error`, `db_error` | Server error. |

## Request tracing

Successful responses include:

```http
x-request-id: req_cm_...
x-crossmodel-model: vendor/model
```

When you report a problem, include as much of this as you can:

- `x-request-id`
- the request time
- the model ID used
- the HTTP status code
- the error response body

## Streaming errors

When an error happens after a streaming connection is already open, it comes back as an SSE event in the matching protocol:

- Chat Completions sends a `data:` chunk with an `error` field.
- Responses sends `event: error`.
- Messages sends an Anthropic-style `error` event.

Once you receive a streaming error, treat that generation as failed. The client can let the user retry, or your business layer can start a fresh, complete request.

## Debugging order

1. `401`: check the headers, that the key starts with `cm-`, and that the key is still usable.
2. `402`: check the console balance, top up, and retry.
3. `404`: call `/v1/models` to confirm the model ID.
4. `429`: lower concurrency or output cap, wait, and try again.
5. `502` / `503`: usually the model service is briefly unavailable — back off and retry.
6. Persistent failures: contact support with the `x-request-id`.
