> ## Индекс документации
> Получите полный индекс документации по адресу: https://api.vega.chat/docs/llms.txt
> Используйте этот файл, чтобы узнать все доступные страницы перед дальнейшим исследованием.

# Ошибки и отладка

> Ошибки API и отладка

```typescript
export const HTTPStatus = {
  S100_Continue: 100,
  S101_Switching_Protocols: 101,
  S102_Processing: 102,
  S200_OK: 200,
  S201_Created: 201,
  S202_Accepted: 202,
  S203_Non_Authoritative_Information: 203,
  S204_No_Content: 204,
  S205_Reset_Content: 205,
  S206_Partial_Content: 206,
  S207_Multi_Status: 207,
  S208_Already_Reported: 208,
  S300_Multiple_Choices: 300,
  S301_Moved_Permanently: 301,
  S302_Found: 302,
  S303_See_Other: 303,
  S304_Not_Modified: 304,
  S305_Use_Proxy: 305,
  S307_Temporary_Redirect: 307,
  S308_Permanent_Redirect: 308,
  S400_Bad_Request: 400,
  S401_Unauthorized: 401,
  S402_Payment_Required: 402,
  S403_Forbidden: 403,
  S404_Not_Found: 404,
  S405_Method_Not_Allowed: 405,
  S406_Not_Acceptable: 406,
  S407_Proxy_Authentication_Required: 407,
  S408_Request_Timeout: 408,
  S409_Conflict: 409,
  S410_Gone: 410,
  S411_Length_Required: 411,
  S412_Precondition_Failed: 412,
  S413_Payload_Too_Large: 413,
  S414_URI_Too_Long: 414,
  S415_Unsupported_Media_Type: 415,
  S416_Range_Not_Satisfiable: 416,
  S417_Expectation_Failed: 417,
  S418_Im_a_teapot: 418,
  S421_Misdirected_Request: 421,
  S422_Unprocessable_Entity: 422,
  S423_Locked: 423,
  S424_Failed_Dependency: 424,
  S425_Too_Early: 425,
  S426_Upgrade_Required: 426,
  S428_Precondition_Required: 428,
  S429_Too_Many_Requests: 429,
  S431_Request_Header_Fields_Too_Large: 431,
  S451_Unavailable_For_Legal_Reasons: 451,
  S498_Invalid_Token: 498,
  S499_Client_Closed_Request: 499,
  S500_Internal_Server_Error: 500,
  S501_Not_Implemented: 501,
  S502_Bad_Gateway: 502,
  S503_Service_Unavailable: 503,
  S504_Gateway_Timeout: 504,
  S505_HTTP_Version_Not_Supported: 505,
  S506_Variant_Also_Negotiates: 506,
  S507_Insufficient_Storage: 507,
  S508_Loop_Detected: 508,
  S510_Not_Extended: 510,
  S511_Network_Authentication_Required: 511,
  S520_Web_Server_Returned_Unknown_Error: 520,
  S521_Web_Server_Is_Down: 521,
  S522_Connection_Timed_Out: 522,
  S523_Origin_Unreachable: 523,
  S524_A_Timeout_Occurred: 524,
  S525_SSL_Handshake_Failed: 525,
  S526_Invalid_SSL_Certificate: 526,
  S529_Overloaded: 529,
  S530_Origin_DNS_Error: 530
};
```

Для ошибок API VEGA возвращает JSON-ответ со следующей структурой:

```typescript
type ErrorResponse = {
  error: {
    code: number;
    message: string;
    metadata?: Record<string, unknown>;
  };
};
```

HTTP‑ответ будет иметь тот же код статуса, что и `error.code`, образуя ошибку запроса, если:

* Ваш исходный запрос некорректен
* Ваш аккаунт VEGA или ключ VEGA исчерпал кредиты VEGA

Во всех остальных случаях возвращаемый HTTP‑статус будет `<code>{HTTPStatus.S200_OK}</code>`, а любые ошибки, возникшие во время генерации LLM, будут переданы в теле ответа или как событие SSE‑данных.

Пример кода для вывода ошибок в JavaScript:

```typescript
const request = await fetch('https://openrouter.ai/...');
console.log(request.status); // Будет код ошибки, если модель не начала обработку запроса
const response = await request.json();
console.error(response.error?.code); // Будет код ошибки
console.error(response.error?.message);
```

## Коды ошибок

* **{HTTPStatus.S400_Bad_Request}**: Bad Request (некорректные или отсутствующие параметры, CORS)
* **{HTTPStatus.S401_Unauthorized}**: Неверные учётные данные (сессия OAuth истекла, отключённый/некорректный ключ VEGA)
* **{HTTPStatus.S402_Payment_Required}**: Ваш аккаунт или ключ VEGA имеет недостаточно кредитов VEGA. Добавьте больше кредитов VEGA и повторите запрос.
* **{HTTPStatus.S403_Forbidden}**: Запрещено (недостаточно прав, блокировка guardrail, или флаг модерации)
* **{HTTPStatus.S408_Request_Timeout}**: Время вашего запроса истекло
* **{HTTPStatus.S429_Too_Many_Requests}**: Вы попали под ограничение скорости
* **{HTTPStatus.S502_Bad_Gateway}**: Выбранная модель недоступна или мы получили некорректный ответ от неё
* **{HTTPStatus.S503_Service_Unavailable}**: Нет доступного провайдера модели, удовлетворяющего вашим требованиям маршрутизации

## Заголовок Retry-After

При ответах с кодами <code>{HTTPStatus.S429_Too_Many_Requests}</code> и <code>{HTTPStatus.S503_Service_Unavailable}</code> API VEGA может включать стандартный HTTP `Retry-After` заголовок, указывающий, сколько секунд ждать перед повторной попыткой.

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
```

SDK OpenAI, Anthropic SDK, Vercel AI SDK и API VEGA SDK уже учитывают этот заголовок для обратного отката. Если вы используете `fetch` напрямую, соблюдайте его перед повторной попыткой:

```typescript
const res = await fetch('https://openrouter.ai/api/v1/chat/completions', { ... });
if (res.status === 429 || res.status === 503) {
  const retryAfter = Number(res.headers.get('Retry-After'));
  if (Number.isFinite(retryAfter) && retryAfter > 0) {
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
    // повторить запрос
  }
}
```

## Ошибки модерации

Если ваш ввод был помечен, `error.metadata` будет содержать информацию о проблеме. Структура метаданных выглядит так:

```typescript
type ModerationErrorMetadata = {
  reasons: string[]; // Почему ваш ввод был помечен
  flagged_input: string; // Текстовый сегмент, который был помечен, ограниченный 100 символами. Если помеченный ввод длиннее 100 символов, он будет усечён посередине и заменён на ...
  provider_name: string; // Название провайдера, запросившего модерацию
  model_slug: string;
};
```

## Ошибки guardrail

На эндпоинтах инференса (`/chat/completions`, `/responses`, `/messages`) запрос может быть заблокирован до того, как он достигнет провайдера — например, фильтром контента или детектором внедрения подсказки, настроенным через [guardrails](/docs/guides/features/guardrails). Когда это происходит, ответ имеет статус `403` с сообщением, описывающим причину блокировки. Тело ответа в формате API VEGA ниже применяется к `/chat/completions` и `/responses`; на `/messages` блок возвращается как оболочка Anthropic `permission_error` (см. [Anthropic Messages](#anthropic-messages-apiv1messages) ниже), при этом `openrouter_metadata` всё ещё передаётся на верхнем уровне, если включён соответствующий флаг:

```json
{
  "error": {
    "code": 403,
    "message": "Request blocked: prompt injection patterns detected",
    "metadata": {
      "patterns": ["ignore all previous instructions"]
    }
  }
}
```

Когда вы включаете [router metadata](/docs/guides/features/router-metadata) через заголовок `X-OpenRouter-Experimental-Metadata: enabled`, 403‑ответ также включает полный объект `openrouter_metadata` с контекстом маршрутизации и массивом `pipeline`, описывающим пройденные стадии guardrail:

```json
{
  "error": {
    "code": 403,
    "message": "Request blocked: prompt injection patterns detected",
    "metadata": {
      "patterns": ["ignore all previous instructions"]
    }
  },
  "openrouter_metadata": {
    "requested": "openai/gpt-4o",
    "strategy": "direct",
    "region": "iad",
    "summary": "available=1",
    "attempt": 1,
    "is_byok": false,
    "endpoints": {
      "total": 1,
      "available": [
        { "provider": "OpenAI", "model": "openai/gpt-4o", "selected": false }
      ]
    },
    "pipeline": [
      {
        "type": "guardrail",
        "name": "regex_pi_detection",
        "guardrail_id": "grd_abc123",
        "guardrail_scope": "api-key",
        "summary": "Blocked: prompt injection detected (1 pattern matched)",
        "data": {
          "action": "blocked",
          "detected": true,
          "engines": ["regex"],
          "patterns": ["ignore all previous instructions"]
        }
      }
    ]
  }
}
```

Объект `openrouter_metadata` следует той же структуре, что и в успешных ответах — см. [Pipeline Stages](/docs/guides/features/router-metadata#pipeline-stages) для полного описания типов стадий и полей.

## Ошибки провайдера

API VEGA нормализует каждую ошибку upstream‑провайдера в стабильный типизированный словарь `error_type`, описанный в разделе [Typed Error Codes](#typed-error-codes). Те же значения `error_type` описывают, что пошло не так, независимо от того, приходит ли ошибка провайдера в теле не‑стримингового ответа или как событие SSE в середине потока. Нативные коды протокола (Anthropic `error.type`, Responses `error.code`) являются приближенными и могут различаться между форматами — `error_type` является полем, на которое следует опираться во всех случаях.

Для Chat Completions ошибка провайдера, прерывающая генерацию, содержит `error_type` внутри `error.metadata`:

```json
{
  "error": {
    "code": 429,
    "message": "Rate limit exceeded",
    "metadata": {
      "error_type": "rate_limit_exceeded",
      "provider_code": "rate_limited"
    }
  }
}
```

То же значение передаётся в ошибках посередине потока и в скинах Anthropic и Responses — см. [Skin-Specific Error Formats](#skin-specific-error-formats) для точного расположения в каждом формате.

### Маскирование и сырые детали провайдера

Когда запрос завершается с кодом `500`, `message` заменяется на общее сообщение, а `provider_code` и `openrouter_metadata` опускаются, но `error_type` остаётся (`server`).

Для ошибок, не являющихся `500`, оригинальный код ошибки провайдера отображается в `error.metadata.provider_code`, если он доступен. При включённом контексте маршрутизации (какой провайдер был выбран, попытки fallback и т.д.) информация передаётся в объекте `openrouter_metadata` при установке заголовка `X-OpenRouter-Metadata` — он имеет ту же структуру, что и в успешных ответах (только поля сводки маршрутизации; см. [Pipeline Stages](/docs/guides/features/router-metadata#pipeline-stages)).

## Когда контент не генерируется

Иногда модель может не сгенерировать никакого контента. Это обычно происходит, когда:

* Модель прогревается после холодного старта
* Система масштабируется для обработки большего количества запросов

Время прогрева обычно составляет от нескольких секунд до нескольких минут, в зависимости от модели и провайдера.

Если вы сталкиваетесь с постоянными проблемами отсутствия контента, рассмотрите возможность простого механизма повторных попыток или попробуйте другой провайдер или модель с более свежей активностью.

В некоторых случаях вы всё равно можете быть начислены за обработку подсказки upstream‑провайдером, даже если контент не был сгенерирован.

## Форматы ошибок при стриминге

При использовании режима стриминга (`stream: true`) ошибки обрабатываются по‑разному в зависимости от того, когда они происходят:

### Ошибки до начала стрима

Ошибки, возникшие до отправки любых токенов, следуют стандартному формату ошибок, описанному выше, с соответствующими HTTP‑кодами. На этом этапе HTTP‑ответ ещё не отправлен, поэтому API VEGA может:

* Вернуть корректный HTTP‑код ошибки (4xx/5xx)
* Тихо повторить запрос к другому провайдеру, если включён [fallback routing](/docs/guides/routing/provider-selection)
* Применить проверки ограничения скорости или аутентификации до начала работы

Вы увидите такие ошибки при некорректных ключах VEGA, неверных запросах или когда все доступные эндпоинты провайдеров исчерпаны до начала стриминга.

### Ошибки в середине стрима

Как только первый токен отправлен клиенту, статус `200 OK` и заголовки уже зафиксированы — их нельзя изменить. Если провайдер падает в этот момент, API VEGA **не может** тихо переключиться на другого провайдера, потому что часть контента уже доставлена вашему приложению. Ошибка должна быть передана в‑полосе как событие SSE.

Типичные причины ошибок в середине стрима:

* **Отключение провайдера** — upstream‑соединение прерывается после частичного вывода (проблема сети, сбой провайдера, таймаут балансировщика)
* **Таймаут провайдера** — модель перестаёт отвечать посередине генерации, и срок чтения истекает
* **Превышение лимита токенов во время генерации** — модель достигает `max_tokens` или заполняет контекстное окно
* **Фильтр контента вывода** — система модерации помечает сгенерированный текст после того, как часть его уже была передана
* **Перегрузка провайдера** — upstream возвращает ошибку ограничения скорости или ёмкости после начала стриминга

<Note>
  Если ошибка происходит до отправки любого токена — даже при запросе со стримингом — API VEGA всё ещё может тихо переключиться на резервный провайдер. Ошибки в середине стрима возникают только после того, как часть контента уже зафиксирована в вашем потоке, делая переключение невозможным.
</Note>

Ошибки в середине стрима отправляются как Server‑Sent Events (SSE) с унифицированной структурой, включающей как детали ошибки, так и завершённый выбор:

```typescript
type MidStreamError = {
  id: string;
  object: 'chat.completion.chunk';
  created: number;
  model: string;
  provider: string;
  error: {
    code: number;       // HTTP‑код статуса (например 400, 429, 502)
    message: string;
    metadata?: {
      error_type: string;     // Типизированный код ошибки — см. таблицу ниже
      provider_code?: string; // Оригинальный код upstream‑провайдера (опущен в 500‑х)
    };
  };
  choices: [{
    index: 0;
    delta: { content: '' };
    finish_reason: 'error';
    native_finish_reason?: string;
  }];
};
```

Пример данных SSE:

```text
data: {"id":"gen-abc123","object":"chat.completion.chunk","created":1234567890,"model":"openai/gpt-4o","provider":"OpenAI","error":{"code":429,"message":"Rate limit exceeded","metadata":{"error_type":"rate_limit_exceeded"}},"choices":[{"index":0,"delta":{"content":""},"finish_reason":"error"}]}
```

Ключевые характеристики:

* Ошибка появляется **на верхнем уровне** вместе со стандартными полями ответа
* `error.metadata.error_type` содержит типизированный код, который можно программно обрабатывать — см. [Typed Error Codes](#typed-error-codes)
* В массиве `choices` присутствует `finish_reason: "error"` для корректного завершения потока
* HTTP‑статус остаётся `200 OK`, так как заголовки уже отправлены
* Поток завершается после этого события
* В ошибках класса 500 `error.message` заменяется на общее сообщение, а `provider_code` опускается, чтобы не раскрывать детали upstream‑провайдера

## Типизированные коды ошибок

Когда ошибка провайдера достигает вашего приложения, API VEGA помечает её канонической строкой `error_type` — как в не‑стриминговом теле ответа, так и в событиях SSE посередине потока. Используйте это значение, а не только HTTP‑статус, для программного различения категорий ошибок. Оно стабильно во всех трёх API‑скинах, даже если нативный код протокола потерян.

Где `error_type` появляется, зависит от скина и пути:

* **Chat Completions**: `error.metadata.error_type` — в ошибочном чанке посередине потока (см. [Mid‑Stream Errors](#mid-stream-errors)) и в не‑стриминговом ответе, когда ошибка провайдера прерывает генерацию.
* **Anthropic Messages**: `error.error_type` в событии SSE `error` и в не‑стриминговом конверте ошибки.
* **Responses**: `error_type` на верхнем уровне в не‑стриминговом JSON‑теле и в событии `response.failed` при стриминге.

Код HTTP, соответствующий каждому `error_type`, перечислен в таблицах ниже.

### Ограничения токенов и длины

| `error_type`              | HTTP‑статус                     | Описание                                                                                                                 |
| ------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `context_length_exceeded` | {HTTPStatus.S400_Bad_Request}  | Совокупное количество входных и выходных токенов превышает контекстное окно модели.                                      |
| `max_tokens_exceeded`     | {HTTPStatus.S400_Bad_Request}  | Генерация остановлена, потому что достигнут `max_tokens` (или `max_completion_tokens`).                                   |
| `token_limit_exceeded`    | {HTTPStatus.S400_Bad_Request}  | Превышен бюджет токенов, установленный API VEGA (например, ограничение по кредитам).                                      |
| `string_too_long`         | {HTTPStatus.S400_Bad_Request}  | Одна строка в запросе (system prompt, пользовательское сообщение и т.д.) превышает ограничение провайдера по символам.   |

### Аутентификация и авторизация

| `error_type`        | HTTP‑статус                        | Описание                                                                                                                |
| ------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `authentication`    | {HTTPStatus.S401_Unauthorized}     | Ключ VEGA отсутствует, некорректен или отозван.                                                                          |
| `permission_denied` | {HTTPStatus.S403_Forbidden}        | Ключ действителен, но не имеет требуемых прав, либо запрос заблокирован [guardrail](/docs/guides/features/guardrails). |
| `payment_required`  | {HTTPStatus.S402_Payment_Required} | У аккаунта VEGA или ключа VEGA недостаточно кредитов VEGA. [Добавьте кредиты VEGA](https://api.vega.chat/credits) и повторите. |

### Ограничения скорости и доступность

| `error_type`           | HTTP‑статус                           | Описание                                                                                                                                  |
| ---------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `rate_limit_exceeded`  | {HTTPStatus.S429_Too_Many_Requests}   | Достигнут лимит запросов или токенов. Уважайте заголовок `Retry-After` перед повтором.                                                    |
| `provider_overloaded`  | {HTTPStatus.S503_Service_Unavailable} | В upstream‑провайдере временная перегрузка. Повторите запрос после небольшой задержки.                                                       |
| `provider_unavailable` | {HTTPStatus.S502_Bad_Gateway}         | В upstream‑провайдере получен некорректный или пустой ответ. API VEGA может автоматически повторить запрос к другому провайдеру, если включён fallback routing. |

### Проверка запросов

| `error_type`          | HTTP‑статус                            | Описание                                                                                   |
| --------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------- |
| `invalid_request`     | {HTTPStatus.S400_Bad_Request}          | Параметр запроса malformed или отсутствует.                                                |
| `invalid_prompt`      | {HTTPStatus.S400_Bad_Request}          | Конкретное сообщение в массиве `messages` некорректно (например, неподдерживаемая роль, пустой контент). |
| `not_found`           | {HTTPStatus.S404_Not_Found}            | Запрашиваемый ресурс (модель, файл и т.д.) не существует.                                 |
| `precondition_failed` | {HTTPStatus.S412_Precondition_Failed}  | Заголовок предусловия (например, `If-Match`) не выполнен.                                 |
| `payload_too_large`   | {HTTPStatus.S413_Payload_Too_Large}    | Тело запроса превышает максимально допустимый размер.                                        |
| `unprocessable`       | {HTTPStatus.S422_Unprocessable_Entity} | Запрос синтаксически корректен, но семантически не может быть обработан.                  |

### Политика контента

| `error_type`               | HTTP‑статус                     | Описание                                                                                  |
| -------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------ |
| `content_policy_violation` | {HTTPStatus.S400_Bad_Request}  | Ввод или вывод был помечен фильтром контента (на уровне провайдера или API VEGA).        |
| `refusal`                  | {HTTPStatus.S400_Bad_Request}  | Модель явно отказалась выполнять запрос (например, из соображений безопасности).        |

### Ошибки изображений

| `error_type`               | HTTP‑статус                     | Описание                                                                                                   |
| -------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `invalid_image`            | {HTTPStatus.S400_Bad_Request}  | Изображение в запросе повреждено или нечитаемо.                                                             |
| `image_too_large`          | {HTTPStatus.S400_Bad_Request}  | Изображение превышает максимальный размер файла или пиксельные размеры, установленные провайдером.          |
| `image_too_small`          | {HTTPStatus.S400_Bad_Request}  | Изображение меньше минимальных пиксельных размеров, требуемых провайдером.                                    |
| `unsupported_image_format` | {HTTPStatus.S400_Bad_Request}  | Формат изображения не поддерживается провайдером.                                                          |
| `image_not_found`          | {HTTPStatus.S404_Not_Found}    | URL изображения или ID файла не удалось разрешить.                                                          |
| `image_download_failed`    | {HTTPStatus.S400_Bad_Request}  | API VEGA не смог загрузить изображение по указанному URL (ошибка DNS, таймаут, ответ не 200 и т.д.).          |

### Общие

| `error_type` | HTTP‑статус                                 | Описание                                                                                                             |
| ------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `server`     | {HTTPStatus.S500_Internal_Server_Error}    | Неожиданная внутренняя ошибка. Сообщение upstream‑провайдера замаскировано в этом типе.                              |
| `timeout`    | {HTTPStatus.S504_Gateway_Timeout}           | Провайдер не ответил в отведённое время.                                                                             |
| `unmapped`   | {HTTPStatus.S500_Internal_Server_Error}    | Ошибка upstream‑провайдера, не попадающая в известные категории. `error.metadata.provider_code` может содержать оригинальный код. |

## Ошибки доступности модели

Когда запрошенная модель не может быть обслужена — она не существует, устарела, не имеет маршрутизируемых эндпоинтов согласно вашим предпочтениям, или все её провайдеры находятся в состоянии полной загрузки — ответ об ошибке содержит дополнительный объект `error.availability`. Он **добавочный**: `error_type`, `http_status` и `message` сохраняют свои значения, поэтому существующая обработка ошибок продолжает работать. Используйте `availability.code` — а не HTTP‑статус или текст сообщения — для программного различения условий доступности.

Тот же объект `availability` включается в чанки ошибок при стриминге для всех трёх API‑скинов (Chat Completions, Responses, Anthropic Messages).

### Коды доступности

Каждое событие недоступности модели сопоставляется ровно одному коду. Коды стабильны навсегда; в будущем могут появиться новые, поэтому неизвестный код следует обрабатывать как `retryable`.

| `availability.code`          | HTTP‑статус                         | `error_type`          | Retryable | Значение                                                                                                                               | Рекомендуемое действие клиента                                                                                     |
| ---------------------------- | ------------------------------------ | --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `model_not_found`            | {HTTPStatus.S400_Bad_Request}        | `invalid_request`     | Нет        | Идентификатор модели неизвестен или некорректен.                                                                                     | Не повторять. Проверьте опечатки в slug или используйте предложения `fallback_models`, если они присутствуют.      |
| `wrong_endpoint`             | {HTTPStatus.S400_Bad_Request}        | `invalid_request`     | Нет        | Модель существует, но вызвана на неверном эндпоинте (например, embedding‑модель на `/chat/completions`).                               | Повторить запрос на эндпоинте, указанном в `constraint.detail`.                                                   |
| `no_endpoints`               | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Модель существует, но не имеет маршрутизируемых эндпоинтов (не настроены, отключены/скрыты, или удалены вашими предпочтениями провайдеров). | Не повторять идентичный запрос. Ослабьте предпочтения маршрутизации провайдера или выберите другую модель.          |
| `model_deprecated`           | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Модель устарела или удалена (sunset‑модели, завершённые stealth‑альфы).                                                            | Перейдите к преемнику в `fallback_models`; см. `docs_url` для уведомления об устаревании.                           |
| `model_unavailable_upstream` | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Каждый эндпоинт модели возвращает 404 upstream — провайдер удалил её.                                                                   | Не повторять запрос. Выберите другую модель (`fallback_models`, если они есть).                                    |
| `capacity_exhausted`         | {HTTPStatus.S429_Too_Many_Requests}  | `rate_limit_exceeded` | Да         | Все провайдеры модели находятся в состоянии полной загрузки (все попытки вернули 429).                                                | Повторить запрос после `retry_after` секунд (также передаётся в заголовке `Retry-After`), либо использовать `fallback_models`. |
| `temporarily_unavailable`    | {HTTPStatus.S503_Service_Unavailable} | `provider_overloaded` | Да         | Все попытки завершились временными 5xx‑ответами upstream или таймаутами.                                                          | Повторить с экспоненциальным откатом, учитывая `retry_after`, если он присутствует; рассмотреть `fallback_models` для чувствительных к задержкам путей. |
| `region_restricted`          | {HTTPStatus.S403_Forbidden}          | `permission_denied`   | Нет        | Модель ограничена географически и недоступна в вашем регионе.                                                                      | Не повторять из того же региона. Настройте предпочтения провайдера или обслуживайте трафик из разрешённого региона. |
| `privacy_restricted`         | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Ваши предпочтения политики данных (ZDR, отказ от обучения, публикация бесплатных моделей) исключили все эндпоинты.                 | Снимите ограничение, указанное в `excluded_by` (например, в [privacy settings](https://api.vega.chat/settings/privacy)), либо выберите другую модель. |
| `constraint_filtered`        | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Ограничение маршрутизации — максимальная цена, длина контекста, `require_parameters`, квантизация, регион данных — исключили все эндпоинты. | Ослабьте ограничение, указанное в `constraint.field` / `excluded_by`, и повторите запрос.                         |
| `free_variant_ended`         | {HTTPStatus.S404_Not_Found}          | `not_found`           | Нет        | Промо‑вариант `:free` завершён; остались только платные эндпоинты.                                                                | Перейдите к платному slug в `fallback_models` (применяется обычное ценообразование) или выберите другую модель.   |

<Note>`no_endpoints` и `model_unavailable_upstream` сегодня не являются повторяемыми, но роутер может пометить отдельные случаи как `retryable: true`, если подлежащая причина временная. Всегда проверяйте `availability.retryable`, а не только код.</Note>

### Объект `availability`

```typescript
type AvailabilityError = {
  code: string;                        // один из кодов выше — машинно‑читаемый дискриминатор
  retryable: boolean;                  // может ли идентичный повтор завершиться успешно?
  retry_after?: number | null;         // секунды ожидания перед повтором, если известны (пути 429/503)
  requested_models: string[];          // исходные slug‑модели, которые вы отправили
  affected_providers?: string[] | null; // провайдеры, эндпоинты которых были попытаны или исключены
  excluded_by?: string[];              // фильтры маршрутизации, которые удалили последние эндпоинты
  fallback_models?: string[];          // предложенные альтернативные slug‑модели; могут быть пустыми или отсутствовать
  constraint?: {                       // присутствует при `constraint_filtered` и `wrong_endpoint`
    field: string;                     // например "max_price"
    detail: string;                    // человекочитаемое объяснение
  };
  docs_url: string;                    // якорь для этого кода на текущей странице
};
```

`code`, `retryable`, `requested_models` и `docs_url` всегда присутствуют в ошибке доступности. Другие поля опускаются (не сериализуются как пустые строки), если не применимы. Значения `excluded_by` берутся из фиксированного словаря: `geo`, `data_region`, `data_policy:zdr`, `data_policy:training`, `max_price`, `context_length`, `require_parameters`, `quantization`, `allowed_providers`.

Для отладки `error.metadata.previous_errors` содержит историю попыток провайдера в компактной, стабильной форме — `{ "provider": "...", "code": "...", "status": 429 }` — и никогда не включает сырые тела ошибок upstream‑провайдера.

### Повтор с `retry_after`

Для `capacity_exhausted` и `temporarily_unavailable` `availability.retry_after` дублирует заголовок `Retry-After` в теле и заполняется, когда любой из попытанных эндпоинтов предоставил подсказку о повторе (минимум среди попыток). Оба значения выражаются в секундах:

```typescript
const res = await fetch('https://openrouter.ai/api/v1/chat/completions', { ... });
const body = await res.json();
const availability = body.error?.availability;
if (availability?.retryable) {
  const waitSeconds =
    availability.retry_after ??
    Number(res.headers.get('Retry-After')) ||
    2 ** attempt; // экспоненциальный откат, если подсказка отсутствует
  await new Promise((r) => setTimeout(r, waitSeconds * 1000));
  // повторить идентичный запрос
}
```

SDK OpenAI, Anthropic, Vercel AI и API VEGA SDK уже учитывают заголовок `Retry-After`; `availability.retry_after` предоставляет тот же сигнал клиентам, которые читают тело вместо заголовков.

### Использование предложений `fallback_models`

`fallback_models` содержит альтернативные slug‑модели, которые роутер может предложить дешево — платный вариант после окончания `:free`‑промо, преемник устаревшей модели или альтернативы той же семьи. Поле опускается, если предложений нет, и никогда не задерживает ответ об ошибке.

Предложения — лишь подсказки, а не гарантии: fallback‑модель может отличаться по цене, контекстному окну или возможностям, и может быть недоступна при ваших предпочтениях маршрутизации. Проверьте slug относительно ваших требований (или покажите пользователю) перед автоматическим переключением.

### Примеры полезных нагрузок ошибок доступности

**Все провайдеры на пределе — `capacity_exhausted` (повторяемо):**

```json
{
  "error": {
    "message": "All providers for anthropic/claude-sonnet-4.5 are at capacity. Retry after 40 seconds.",
    "error_type": "rate_limit_exceeded",
    "http_status": 429,
    "availability": {
      "code": "capacity_exhausted",
      "retryable": true,
      "retry_after": 40,
      "requested_models": ["anthropic/claude-sonnet-4.5"],
      "affected_providers": ["anthropic", "amazon-bedrock", "google-vertex"],
      "fallback_models": ["anthropic/claude-haiku-4.5"],
      "docs_url": "https://api.vega.chat/docs/errors#capacity_exhausted"
    },
    "metadata": {
      "previous_errors": [
        { "provider": "anthropic", "code": "capacity_exhausted", "status": 429 },
        { "provider": "amazon-bedrock", "code": "capacity_exhausted", "status": 429 }
      ]
    }
  }
}
```

**Устаревшая stealth‑модель — `model_deprecated`:**

```json
{
  "error": {
    "message": "Quasar Alpha was a stealth model, revealed on April 14th as an early testing version of GPT-4.1.",
    "error_type": "not_found",
    "http_status": 404,
    "availability": {
      "code": "model_deprecated",
      "retryable": false,
      "requested_models": ["openrouter/quasar-alpha"],
      "fallback_models": ["openai/gpt-4.1"],
      "docs_url": "https://api.vega.chat/docs/errors#model_deprecated"
    }
  }
}
```

**Ограничения конфиденциальности исключили все эндпоинты — `privacy_restricted`:**

```json
{
  "error": {
    "message": "No endpoints for openai/gpt-5.2 match your data policy (zero data retention). Adjust at https://api.vega.chat/settings/privacy.",
    "error_type": "not_found",
    "http_status": 404,
    "availability": {
      "code": "privacy_restricted",
      "retryable": false,
      "requested_models": ["openai/gpt-5.2"],
      "affected_providers": ["openai", "azure"],
      "excluded_by": ["data_policy:zdr"],
      "docs_url": "https://api.vega.chat/docs/errors#privacy_restricted"
    }
  }
}
```

**Неизвестный идентификатор модели — `model_not_found`:**

```json
{
  "error": {
    "message": "acme/fake-1.0 is not a valid model ID",
    "error_type": "invalid_request",
    "http_status": 400,
    "availability": {
      "code": "model_not_found",
      "retryable": false,
      "requested_models": ["acme/fake-1.0"],
      "docs_url": "https://api.vega.chat/docs/errors#model_not_found"
    }
  }
}
```

## Форматы ошибок, специфичные для скинов

API VEGA предоставляет три API‑скина. Каждый переводит одинаковые внутренние типы ошибок провайдера в свой собственный формат, как для не‑стриминговых ответов, так и для ошибок в потоке. Во всех случаях `error_type` остаётся стабильным полем; место его расположения различается в зависимости от скина.

### Chat Completions (`/api/v1/chat/completions`)

Ошибки посередине потока появляются как `chat.completion.chunk` с объектом `error` верхнего уровня (см. выше). Поле `error.metadata.error_type` несёт типизированный код.

Для не‑стриминговых запросов, где происходит ошибка провайдера, ошибка встраивается в окончательный ответ вместе с любой частичной выдачей:

```json
{
  "choices": [{
    "message": { "role": "assistant", "content": "partial output..." },
    "finish_reason": "error",
    "error": {
      "code": 502,
      "message": "Provider disconnected mid-stream",
      "metadata": { "error_type": "provider_unavailable" }
    }
  }]
}
```

### Responses API (`/api/v1/responses`)

Responses API отображает внутренние типы ошибок в набор кодов ошибок OpenAI Responses. Отображение более узкое — многие внутренние типы сводятся к `server_error`, поэтому точная причина сохраняется в поле `error_type` верхнего уровня, вне нативного объекта `error`:

| Внутренний `error_type`                                 | Responses API `code`             |
| ------------------------------------------------------- | -------------------------------- |
| `rate_limit_exceeded`                                   | `rate_limit_exceeded`            |
| `context_length_exceeded`, `invalid_request`          | `invalid_prompt`                 |
| `content_policy_violation`                              | `image_content_policy_violation` |
| `authentication`, `provider_overloaded`, `provider_unavailable`, `timeout`, `server` | `server_error`                   |
| Все остальные (включая `invalid_prompt`)               | `server_error`                   |

Оба — потоковое завершающее событие и не‑стриминговый JSON‑тело — содержат канонический `error_type` на верхнем уровне объекта ответа. Например, ошибка аутентификации сводится к нативному коду `server_error`, но сохраняет `error_type: "authentication"`:

```json
{
  "id": "resp_abc123",
  "status": "failed",
  "error": { "code": "server_error", "message": "Invalid credentials" },
  "error_type": "authentication"
}
```

Ошибки в потоке передаются как один из трёх SSE‑событий, каждый оборачивает тот же объект ответа:

1. **`response.failed`** — завершающее событие, когда ответ не может быть завершён:
   ```json
   {
     "type": "response.failed",
     "response": {
       "id": "resp_abc123",
       "status": "failed",
       "error": { "code": "server_error", "message": "Internal server error" },
       "error_type": "server"
     }
   }
   ```

2. **`response.error`** — ошибка во время генерации ответа:
   ```json
   {
     "type": "response.error",
     "error": { "code": "rate_limit_exceeded", "message": "Rate limit exceeded" }
   }
   ```

3. **`error`** — обычное событие ошибки (соответствует поведению OpenAI):
   ```json
   {
     "type": "error",
     "error": { "code": "invalid_api_key", "message": "Invalid API key provided" }
   }
   ```

#### Преобразования кодов ошибок

Некоторые ошибки, связанные с токенами/длиной, преобразуются в успешные завершения вместо сбоев:

| `error_type`              | Преобразовано в | Причина завершения |
| -------------------------- | ---------------- | ------------------- |
| `context_length_exceeded` | Success          | `length`            |
| `max_tokens_exceeded`     | Success          | `length`            |
| `token_limit_exceeded`    | Success          | `length`            |
| `string_too_long`         | Success          | `length`            |

Это позволяет элегантно обрабатывать ошибки, связанные с лимитами, без пометки их как неудач.

### Anthropic Messages (`/api/v1/messages`)

Скин Anthropic Messages отображает внутренние типы в строки ошибок Anthropic:

| Внутренний `error_type`                                 | Anthropic `error.type`          |
| ------------------------------------------------------- | -------------------------------- |
| `authentication`                                        | `authentication_error`          |
| `permission_denied`                                      | `permission_error`               |
| `payment_required`                                       | `billing_error`                  |
| `not_found`, `image_not_found`                           | `not_found_error`                |
| `rate_limit_exceeded`                                    | `rate_limit_error`               |
| `provider_overloaded`                                    | `overloaded_error`               |
| `timeout`                                                | `timeout_error`                  |
| `context_length_exceeded`, `content_policy_violation`, `invalid_request`, ... | `invalid_request_error` |
| `provider_unavailable`, `server`, `unmapped`, ...      | `api_error`                      |

Поскольку нативный `error.type` является потерянным (многие внутренние типы сводятся к `api_error`), канонический `error_type` добавляется внутри объекта `error` рядом с ним. Это справедливо как для не‑стримингового конверта ошибки, так и для SSE‑события `error`.

Не‑стриминговый конверт ошибки (ошибки до роутера, такие как ошибки аутентификации, имеют `request_id: null`; пост‑роутерные ошибки содержат `gen-`‑идентификатор):

```json
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid credentials",
    "error_type": "authentication"
  },
  "request_id": null
}
```

Ошибки посередине потока отправляются как SSE‑событие `error` с тем же форматом:

```json
{
  "type": "error",
  "error": {
    "type": "overloaded_error",
    "message": "Provider is temporarily overloaded",
    "error_type": "provider_overloaded"
  }
}
```

## Отладка

API VEGA предоставляет параметр `debug`, позволяющий вам увидеть точное тело запроса, отправленное upstream‑провайдеру. Это работает как с Chat Completions API (`/api/v1/chat/completions`), так и с Responses API (`/api/v1/responses`). Полезно для понимания того, как API VEGA трансформирует ваши параметры запроса для разных провайдеров.

### Структура параметра debug

Параметр debug — объект со следующей структурой:

```typescript
type DebugOptions = {
  echo_upstream_body?: boolean; // Если true, возвращает трансформированное тело запроса, отправленное провайдеру
};
```

### Использование

Чтобы включить вывод отладки, добавьте параметр `debug` в ваш запрос:

#### Chat Completions

<CodeGroup>
  ```typescript title="TypeScript" expandable
  fetch('https://openrouter.ai/api/v1/chat/completions', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer <OPENROUTER_API_KEY>',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'anthropic/claude-haiku-4.5',
      stream: true, // Отладка работает только со стримингом
      messages: [
        { role: 'system', content: 'You are a helpful assistant.' },
        { role: 'user', content: 'Hello!' },
      ],
      debug: {
        echo_upstream_body: true,
      },
    }),
  });

  const text = await response.text();

  for (const line of text.split('\n')) {
    if (!line.startsWith('data: ')) continue;

    const data = line.slice(6);
    if (data === '[DONE]') break;

    const parsed = JSON.parse(data);

    if (parsed.debug?.echo_upstream_body) {
      console.log('\nDebug:', JSON.stringify(parsed.debug.echo_upstream_body, null, 2));
    }

    process.stdout.write(parsed.choices?.[0]?.delta?.content ?? '');
  }
  ```

  ```python title="Python" expandable
  import requests
  import json

  response = requests.post(
    url="https://openrouter.ai/api/v1/chat/completions",
    headers={
      "Authorization": "Bearer <OPENROUTER_API_KEY>",
      "Content-Type": "application/json",
    },
    data=json.dumps({
      "model": "anthropic/claude-haiku-4.5",
      "stream": True,
      "messages": [
        { "role": "system", "content": "You are a helpful assistant." },
        { "role": "user", "content": "Hello!" }
      ],
      "debug": {
        "echo_upstream_body": True
      }
    }),
    stream=True
  )

  for line in response.iter_lines():
    if line:
      text = line.decode('utf-8')
      if 'echo_upstream_body' in text:
        print(text)
  ```
</CodeGroup>

#### Responses API

<CodeGroup>
  ```typescript title="TypeScript" expandable
  fetch('https://openrouter.ai/api/v1/responses', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer <OPENROUTER_API_KEY>',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'anthropic/claude-haiku-4.5',
      stream: true,
      input: 'Hello!',
      debug: {
        echo_upstream_body: true,
      },
    }),
  });

  const text = await response.text();

  for (const line of text.split('\n')) {
    if (!line.startsWith('data: ')) continue;

    const data = line.slice(6);
    if (data === '[DONE]') break;

    const parsed = JSON.parse(data);

    if (parsed.type === 'response.debug') {
      console.log('\nDebug:', JSON.stringify(parsed.debug, null, 2));
    }
  }
  ```

  ```python title="Python" expandable
  import requests
  import json

  response = requests.post(
    url="https://openrouter.ai/api/v1/responses",
    headers={
      "Authorization": "Bearer <OPENROUTER_API_KEY>",
      "Content-Type": "application/json",
    },
    data=json.dumps({
      "model": "anthropic/claude-haiku-4.5",
      "stream": True,
      "input": "Hello!",
      "debug": {
        "echo_upstream_body": True
      }
    }),
    stream=True
  )

  for line in response.iter_lines():
    if line:
      text = line.decode('utf-8')
      if 'response.debug' in text:
        print(text)
  ```
</CodeGroup>

### Формат ответа отладки

#### Chat Completions

Когда `debug.echo_upstream_body` установлен в `true`, API VEGA отправляет отладочный чанк **первым** в стриминговом ответе. Этот чанк имеет пустой массив `choices` и включает поле `debug` с трансформированным телом запроса:

```json
{
  "id": "gen-xxxxx",
  "provider": "Anthropic",
  "model": "anthropic/claude-haiku-4.5",
  "object": "chat.completion.chunk",
  "created": 1234567890,
  "choices": [],
  "debug": {
    "echo_upstream_body": {
      "system": [
        { "type": "text", "text": "You are a helpful assistant." }
      ],
      "messages": [
        { "role": "user", "content": "Hello!" }
      ],
      "model": "claude-haiku-4-5-20251001",
      "stream": true,
      "max_tokens": 64000,
      "temperature": 1
    }
  }
}
```

#### Responses API

В Responses API отладочные данные приходят как SSE‑событие `response.debug`:

```json
{
  "type": "response.debug",
  "debug": {
    "echo_upstream_body": {
      "model": "claude-haiku-4-5-20251001",
      "messages": [
        { "role": "user", "content": "Hello!" }
      ],
      "stream": true,
      "max_tokens": 64000,
      "temperature": 1
    }
  },
  "sequence_number": 0
}
```

### Важные замечания

<Warning>
  **Только стриминг**

  Параметр `debug` **работает только в режиме стриминга** (`stream: true`). Запросы без стриминга игнорируют параметр отладки.
</Warning>

<Warning>
  **Не для продакшна**

  Флаг отладки **не следует использовать в продакшн‑окружениях**. Он предназначен исключительно для разработки и отладки, так как может раскрывать чувствительные данные, включённые в запрос, которые не предназначены для публичного доступа.
</Warning>

### Сценарии использования

Отладочный вывод особенно полезен для:

1. **Понимания трансформаций параметров**: увидеть, как API VEGA преобразует ваши параметры в формат, специфичный для провайдера (например, как задаётся `max_tokens`, как обрабатывается `temperature`).
2. **Проверки форматирования сообщений**: убедиться, как API VEGA объединяет и форматирует ваши сообщения для разных провайдеров (например, как склеиваются system‑сообщения, как объединяются пользовательские сообщения).
3. **Проверки применённых значений по умолчанию**: увидеть, какие значения по умолчанию подставляет API VEGA, если параметры не указаны в запросе.
4. **Отладки переключения провайдеров**: при использовании fallback‑провайдеров отладочный чанк будет отправлен **для каждого попытанного провайдера**, позволяя увидеть, какие провайдеры были пробованы и какие параметры были отправлены каждому.

## Конфиденциальность и редактирование

API VEGA приложит все усилия для автоматического редактирования потенциально чувствительных или шумных данных в отладочном выводе. Помните, что параметр отладки не предназначен для продакшна.