# Errors

> The error shape and what each status code means.

Errors use OpenAI’s shape, so the OpenAI SDKs raise their usual exception types.

```json
{
  "error": {
    "message": "Your credit balance has run out. Add credits at https://clonvo.com/app/acme/credits, or add your own provider key at https://clonvo.com/app/acme/integrations.",
    "type": "insufficient_credits",
    "code": "insufficient_credits",
    "param": null
  }
}
```

| Field | Description |
| --- | --- |
| `message` | What went wrong and what to do next, in plain language. Errors from a provider start with the provider’s name, for example `Anthropic: …`. Safe to log; don’t show it to end users verbatim. |
| `type` | Error category: `invalid_request_error`, `authentication_error`, `permission_error`, `not_found_error`, `insufficient_credits`, `rate_limit_error`, `server_error`, `service_unavailable` or `timeout_error`. Provider errors can carry other provider-specific types. |
| `code` | A more specific code (see below), or `null`. |
| `param` | The request parameter at fault, such as `model` or `messages[0].content`, or `null`. |

Chat completion, [Responses API](https://clonvo.com/docs/responses.md), [embeddings](https://clonvo.com/docs/embeddings.md) and [tool](https://clonvo.com/docs/tools.md) responses carry the generation id in an `x-clonvo-generation-id` header, errors included, so you can look up a failed request with [`GET /v1/generation`](https://clonvo.com/docs/other-endpoints.md#get-v1-generation). Authentication failures and bodies that aren’t valid JSON are the exception: they’re rejected before a generation is created.

## Status codes

| Status | Codes | When, and what to do |
| --- | --- | --- |
| `400` | `invalid_json`, `invalid_request`, `model_required`, `too_many_models`, `model_not_found`, `unsupported_parameter`, `unsupported_content`, `provider_key_rejected`, `provider_requires_own_key`, `missing_parameter`, `no_allowed_credentials`, `media_too_large` | The request is invalid: malformed JSON, a missing or wrong parameter, an unknown model id, more than 5 fallback models, tools or content the model doesn’t accept, or a prompt longer than the model’s context. `provider_key_rejected` means your own provider key was refused, or Clonvo couldn’t read it. `provider_requires_own_key` means the model’s provider isn’t available on Clonvo credits yet, so it only runs with your own key for that provider (`param` is `model`).   Fix the request, or add or update the key under **Provider keys**. Retrying won’t help. |
| `400` | `invalid_tool_arguments`, `tool_requires_own_key`, `no_allowed_providers` | From the [tool endpoints](https://clonvo.com/docs/tools.md#errors). `invalid_tool_arguments` means `arguments` doesn’t match the tool’s schema; `param` names the argument, such as `arguments.max_results`. `tool_requires_own_key` means you have no enabled key for any provider that can serve the tool, after your `provider` settings. `no_allowed_providers` means your `provider` settings exclude every provider that serves it.   Fix the arguments, or add a Firecrawl, Tavily, Exa, Parallel or TinyFish key under **Provider keys → Tools**. |
| `400` | `model_not_embedding`, `embedding_model_not_chat`, `invalid_dimensions` | From [embeddings](https://clonvo.com/docs/embeddings.md#errors). `model_not_embedding` means a chat model was sent to `POST /v1/embeddings`; `embedding_model_not_chat` means an embedding model was sent to chat completions (`param` is `model` for both). `invalid_dimensions` means `dimensions` is outside the model’s range; a model with a fixed size returns `unsupported_parameter` instead.   Use an embedding model from `GET /v1/embeddings/models` for embeddings and a chat model for chat, and fix `dimensions`. |
| `401` | `missing_api_key`, `invalid_api_key`, `api_key_revoked`, `api_key_disabled`, `api_key_expired`, `project_archived` | The API key is missing, malformed, unknown, revoked, disabled or expired, or its project is archived.   Check the `Authorization` header and the key in the dashboard. |
| `402` | `insufficient_credits`, `key_limit_exceeded`, `byok_fee_requires_credits` | Your organization’s available balance (after requests in progress) can’t cover this request’s maximum cost, the key’s remaining limit can’t cover it, or your own-key usage is past the monthly allowance and there are no credits for the fee. On Free, any paid model returns `insufficient_credits`.   Buy credits, raise the key’s limit, or wait for the limit to reset. The message says which. |
| `402` | `plan_feature_unavailable`, `byok_requires_paid_plan`, `project_limit_reached` | Your [plan](https://clonvo.com/docs/plans.md) doesn’t include this: `models` or `provider` on Free (`plan_feature_unavailable`), a paid model on Free after adding provider keys, or a model that only runs with your own key (`byok_requires_paid_plan`), or creating or restoring a project over your plan’s limit (`project_limit_reached`, from the dashboard).   Buy credits to move to Pay as you go, or archive a project you don’t use. |
| `403` | `training_providers_not_allowed`, `free_model_terms_required` | A free model was requested, but free models are off for your organization (`training_providers_not_allowed`), or they’re paused until an owner or admin accepts the current free-model data terms (`free_model_terms_required`).   An owner or admin can turn them on, or accept the current terms, in **Settings → Privacy**. Otherwise use a paid model. |
| `404` | `model_unavailable`, `model_retired`, `no_endpoints_for_data_policy`, `model_not_found`, `generation_not_found`, `tool_not_found`, `unknown_endpoint` | The model is temporarily switched off or has been retired, a free model was excluded by `provider.data_collection: "deny"`, or the model, generation, tool or endpoint you asked for doesn’t exist.   Choose another model, use a tool id from `GET /v1/tools`, or check the URL. |
| `405` | `method_not_allowed` | The endpoint exists but not with this HTTP method. The `Allow` header lists the methods it accepts.   Use the listed method. |
| `429` | `rate_limit_exceeded`, `free_model_rate_limited`, `free_model_daily_limit` | Too many requests: the per-key limit, a free model limit, or the provider’s rate limit.   Wait and retry with backoff, or add fallback models. See [Rate limits](https://clonvo.com/docs/rate-limits.md). |
| `500` | `internal_error` | Something went wrong inside Clonvo.   Retry with backoff. |
| `502` | `upstream_error`, `upstream_unreachable`, `upstream_invalid_response` | The provider returned an error or an invalid response, or couldn’t be reached.   Retry, or add fallback models. |
| `503` | `provider_unavailable`, `upstream_overloaded` | The provider is temporarily unavailable or overloaded, or free models can’t be served right now.   Retry later, or add fallback models. |
| `504` | `upstream_timeout` | The provider took too long to respond.   Retry, ideally with a fallback model. |

Other errors from a provider are passed on with the status, type and code Clonvo maps them to, and the provider’s message after its name. A prompt that’s too long for the model’s context comes back from the provider as a `400` and isn’t retried on fallback models. With [fallback models](https://clonvo.com/docs/fallbacks.md), `429`, `5xx` and timeout errors are retried automatically before you see them.

## Errors during streaming

Errors before the stream starts come back as a normal JSON response with one of the statuses above. Errors after streaming has started arrive as a chunk with `finish_reason: "error"` and an `error` object. See [Streaming](https://clonvo.com/docs/streaming.md#errors).

## Handling errors in code

```python
import openai

try:
    completion = client.chat.completions.create(model="openai/gpt-6.1-sol", messages=messages)
except openai.BadRequestError:
    ...  # 400: fix the request (unknown model id, unsupported content, …)
except openai.AuthenticationError:
    ...  # 401: check the key
except openai.PermissionDeniedError:
    ...  # 403: free models need the privacy setting
except openai.NotFoundError:
    ...  # 404: model unavailable or retired
except openai.RateLimitError:
    ...  # 429: back off and retry
except openai.APIStatusError as e:
    if e.status_code == 402:
        ...  # out of credits, the key's spending limit, or not on your plan (e.code)
    else:
        raise
```

The OpenAI SDKs already retry `429` and `5xx` errors a couple of times with backoff. Adjust with `max_retries` on the client.