# Errors and limits

> Original: https://api.6io.io/en/docs/errors-and-limits/ (HTML). All pages: https://api.6io.io/llms.txt

## The error format

As at OpenAI, so SDKs parse it themselves:

```json
{"error": {"message": "Not enough funds on the API balance for this request", "type": "insufficient_funds", "code": "insufficient_funds"}}
```

For programs `code` is what matters: write conditions on it. The `message` text may change.

A provider's answer to an error in your parameters (for example, a model's `400`) comes as it is.

## Codes

### Key and account

| HTTP | `code` | What happened |
| --- | --- | --- |
| 401 | `invalid_api_key` | there is no key in the header, it is wrong, revoked or expired |
| 403 | `account_blocked` | the account is blocked |
| 403 | `account_restricted` | the account is in restricted mode and paid requests are closed; write to support |

### Request

| HTTP | `code` | What happened |
| --- | --- | --- |
| 400 | `invalid_body`, `unsupported_parameter`, `invalid_idempotency_key` | the request is not parsed or uses something not supported yet |
| 400 | `invalid_webhook_url` | the notification address does not fit: not `https`, a private network, the address of this API, too long or not a string |
| 404 | `model_not_found` | an unknown prefix, no such model, or it is not sold |
| 404 | `not_found` | the request, job or task is not found or belongs to another account |
| 413 | `request_too_large` | the request body is too big |

### Money and retries

| HTTP | `code` | What happened |
| --- | --- | --- |
| 402 | `insufficient_funds` | the available funds are not enough, the balance is negative or (for a free model) zero |
| 409 | `idempotent_request_exists` | a request with this `Idempotency-Key` has already been accepted |
| 422 | `idempotency_key_reused` | the same `Idempotency-Key` with a different body |

### Limits

| HTTP | `code` | What happened |
| --- | --- | --- |
| 429 | `rate_limit_exceeded` | too often |
| 429 | `concurrency_limit_exceeded` | all places for simultaneous requests are taken (separately for chat and for images, video and audio) |
| 429 | `too_many_waiting_requests` | too many requests are waiting for a free place |
| 429 | `too_many_unsettled_requests` | too many requests are not yet closed in money |
| 429 | `ip_rate_limit_exceeded`, `ip_blocked`, `too_many_connections` | too many requests or connections from one IP, or the IP is blocked for a while |

### Provider and service

| HTTP | `code` | What happened |
| --- | --- | --- |
| 503 | `service_unavailable` | the service is temporarily unavailable, no money is charged for the request |
| 503 | `upstream_busy` | the provider did not accept the request because of the rate, or could not be reached: nothing is charged, retry after `Retry-After` |
| 502, 503 | `upstream_unavailable` | the provider did not answer, the outcome is being checked, the reserve is held |

### fal and Sixio models

| HTTP | `code` | What happened |
| --- | --- | --- |
| 400 | `invalid_endpoint` | fal: a wrong model ID |
| 400 | `unsupported_model` | fal: the model's price unit is not supported yet |
| 422 | `invalid_input` | Sixio: the task parameters are refused or a file by link is not accepted (the link did not open, it is not a public address, too big, the wrong type). The task is not accepted, no money was reserved |

### Background jobs

| HTTP | `code` | What happened |
| --- | --- | --- |
| 400 | `unsupported_operation` | there is no such operation |
| 409 | `job_failed`, `job_outcome_unknown`, `result_unavailable`, `result_too_large` | there is no result: the job was not done, the outcome is being checked, or the provider did the work but the answer did not reach us or is above the storage limit |
| 410 | `result_expired` | the result's storage time is over |

What to do with each of them is in [Retries and failures](https://api.6io.io/md/en/retries.md).

## Limits

Limits apply to the whole account: all its keys share one limit, and the number of keys does not raise it. The kinds are:

- **rate** of paid requests: the average speed and a burst;
- **simultaneous requests**: how many generations run in parallel;
- **waiting**: if there is no place, a request waits a few seconds before it gets `429`. It does not become a deferred job with a `202` answer;
- **not closed in money**: how many requests are already sent but their amount is not confirmed;
- **reading** (`/models`, `/balance`, `/requests`): counted separately, so frequent status checks do not eat the generation limit.

All `429` answers carry a `Retry-After` header in seconds and a reason code. It is a retry interval, not a promise that a place frees up exactly then. Your own limits and their use are visible in the console, on the Overview tab. The limit values depend on the account and can be changed on request to support.
