Тема
Язык

Ошибки и лимиты

Коды ошибок GetVibe API: 401 (ключ), 402 (баланс), 403 (IP), 429 (лимит запросов). Как обрабатывать ошибки и повторять запросы с экспоненциальной задержкой.

Ошибки, порождаемые GetVibe на /v1/*, имеют JSON-конверт с error.message, error.type и error.code. Не полагайтесь на текст сообщения или заголовки сторонних сервисов как на контракт.

Формат ошибки

{
  "error": {
    "message": "insufficient balance",
    "type": "insufficient_quota",
    "code": 402,
    "request_id": "8d4b6b3a-..."
  }
}

Коды ответа

ПараметрТипОписание
401authentication_error / 401Отсутствует или имеет неверный формат ключ, либо ключ отключён. Не повторяйте попытки, пока учётные данные не будут исправлены.
402insufficient_quota / 402Нет доступного баланса или лимита — ожидание не поможет. Ответ 402 никогда не содержит Retry-After и не подлежит повтору: пополните баланс или дождитесь сброса окна подписки.
403permission_error or policy type / 403IP, модель или политика не разрешают выполнить запрос. Не повторяйте запрос, не изменив сам запрос или настройки.
429rate_limit_exceeded, inflight_client_cap or rate_limit_error / 429Ваш лимит скорости, ваш лимит параллелизма, кратковременно удерживаемый резерв баланса вашими же параллельными запросами (причина reserved_in_flight) или лимит поставщика. Повторяйте только после Retry-After; 429 никогда не означает, что ваш баланс исчерпан.
410media_endpoint_retired / media_endpoint_retiredТолько /v1/images/edits, /v1/video/generations и /v1/videos (выведен из эксплуатации). Не повторяйте запрос; переключитесь на /api/media/generate. /v1/images/generations обслуживается.
413invalid_request_error / 413Только Files API: файл превышает 50 MiB. Уменьшите файл, затем создайте новый запрос.
503overloaded / 503Перегрузка глобального узла. Повторите запрос после Retry-After: 2. Другие ошибки 503 могут не быть повторяемыми без изменения модели или запроса.

Ошибки запросов (400, 413, 422): коды и способы исправления

Каждая ошибка запроса содержит стабильный error.code из таблицы ниже, error.param с именем поля, к которому она относится (null, если модель его не указала), и ссылку на соответствующую строку в конце error.message — Codex и другие CLI показывают только сообщение, поэтому ссылка размещена в нём.

error.codeerror.paramЧто делать
unsupported_parameterимя поляВыбранная модель или канал не принимает этот параметр. Удалите его из запроса (в Codex/IDE — из конфигурации) и повторите попытку.
invalid_parameter_valueимя поляПараметр присутствует, но его значение недопустимо для этой модели: например, temperature отличается от 1 при включённом рассуждении, max_tokens превышает максимум или effort имеет значение "none", когда рассуждение нельзя отключить. Исправьте значение согласно сообщению.
missing_parameterимя поляОбязательное поле отсутствует или пусто. Добавьте его.
invalid_tool_schematools[].function.*Определение инструмента отклонено: в именах допускаются только латинские буквы, цифры, "_" и "-"; параметры должны быть заданы в виде JSON Schema с корневым типом type: "object". Либо выберите другой вариант модели.
tool_choice_unsupportedtool_choiceМодель не поддерживает принудительный выбор инструмента. Передайте tool_choice со значением "auto" или "none".
invalid_tool_historymessages / inputВ истории есть вызов инструмента без результата. Добавьте результат с тем же id или при сокращении истории удалите вызов вместе с его результатом.
invalid_image—Не удалось прочитать изображение. Отправьте полный файл PNG, JPEG, WebP или GIF (BMP, TIFF, AVIF и SVG не принимаются).
unsupported_input_modality—Модель не принимает вложения этого типа (PDF, аудио, видео, изображения). Удалите вложение или выберите модель, в описании которой в каталоге указан этот тип входных данных.
conversation_state_unreadable—Рассуждение в истории создано другим каналом. Запрос корректен; повторите его, а если ошибка повторится, начните новый диалог.
invalid_json—Тело запроса не является JSON или поступило в усечённом виде. Для очень длинных диалогов с изображениями начните новый диалог или сожмите историю.
request_too_large—Запрос слишком большой. Уменьшите объём вложений или истории.
request_rejected_by_channel—Канал модели отклонил запрос без указания причины; сам запрос, скорее всего, корректен. Повторите его; если отказ повторится, выберите другой вариант модели (суффикс после двоеточия) или модель без суффикса. Если это не поможет, обратитесь в службу поддержки и укажите request_id.
model_not_available_on_route—Для этой модели не настроен маршрут. Выберите другую модель или вариант.
context_length_exceededmessages / input / promptЗапрос не помещается в контекстное окно. Сожмите историю (в Codex: /compact) или выберите модель с более широким контекстным окном.
content_moderation—Запрос или ответ заблокирован фильтром содержимого провайдера. Переформулируйте запрос или выберите другую модель.
invalid_request—Причина не распознана. Проверьте запрос по справочнику API; если он корректен, обратитесь в службу поддержки и укажите request_id из ответа.

Заголовки ответа

ПараметрТипОписание
x-pv-cost-rubstringПриблизительная оценка стоимости в рублях. В стримах x-pv-cost-rub доступен, когда оценка по входу известна; pv_cost_rub в финальном событии usage требует x-pv-cost: 1. Фактическое списание указано в истории расхода.
x-pv-generation-idstringИдентификатор записи истории использования (GET /v1/generations/{id}). Возвращается только для нестриминговых запросов chat/completions.
x-pv-dropped-paramsstringПараметры запроса через запятую, которые выбранный маршрут не принимает и которые поэтому не были отправлены в модель (например, temperature,top_p). Присутствует только тогда, когда что-то действительно было отброшено, — как в ответах, так и в ошибках. Мы никогда не отбрасываем параметр молча: отсутствие заголовка означает, что всё отправленное дошло до модели без изменений.
Retry-AfterintegerСекунды ожидания. Edge устанавливает его при 429 rate, 429 concurrency (5), 503 global overload (2) и некоторых временных 402. Не предполагается для каждого 429/503.

Ошибки до и после начала ответа

Медленный поток (stream: true) получает комментарии 200 и : pv-keepalive после 5 секунд молчания, чтобы соединение не выглядело мёртвым; долгий нестриминговый запрос получает 200 и пробелы после первого токена. С этого момента статус измениться не может, а ошибка приходит в теле. Если ваш клиент при ошибке HTTP переключается на другого поставщика, отправьте x-pv-honest-errors: 1 (или попросите поддержку включить это для аккаунта): тогда нет ни keepalive, ни раннего 200 до первого байта ответа, и каждая ошибка — обычный HTTP-статус с телом JSON. Цена — молчащий сокет до первого токена; ваш тайм-аут заголовков должен это покрывать.

Ошибка после начала ответа — это одно терминальное событие: для chat event: error с {"error":{message,type,code,status},"choices":[{"finish_reason":"error"}]}, за которым следует data: [DONE]; для /v1/responses event: response.failed, несущее тот же error; для /v1/messages — event: error от Anthropic. code — это машинная причина, а status — HTTP-статус, который был бы у ошибки, если бы она возникла до начала ответа.

Для потоковых запросов (stream: true) x-pv-generation-id не возвращается, поскольку биллинг завершается после окончания потока. Просматривайте историю запросов через GET /v1/generations.

Лимиты частоты и параллелизма

Оба лимита зависят от текущего баланса аккаунта и применяются ко всем его API-ключам в совокупности. Уровень пересчитывается автоматически: при пополнении баланса лимит повышается, а при снижении баланса ниже порогового значения уровень понижается. Лимита токенов в минуту (TPM) нет.

Баланс отЗапросы в минуту (RPM)Одновременные запросы
0 $30010
1 $1 10050
2 $6 600300
4 $19 800900
12 $44 0002 000
ПараметрТипОписание
429 rate_limit_exceededRPMЗа последние 60 секунд (скользящее окно) аккаунт отправил столько запросов, сколько допускает его уровень. Retry-After — количество секунд до освобождения слота в окне (не менее 1); x-ratelimit-limit-requests — ваш текущий RPM. Тело ответа: error.cause = key_rate_limited, error.details = { enforced_by: "getvibe", limit, unit: "requests_per_minute", retry_after_seconds }.
429 inflight_client_capconcurrencyУже выполняется столько запросов, сколько допускает уровень. Запрос занимает слот до завершения; поток — до последнего события. Retry-After: 5. Тело ответа: error.cause = account_concurrency_limited, error.details = { enforced_by: "getvibe", limit, unit: "parallel_requests", retry_after_seconds: 5 }.
Personal limitRPMЕсли для аккаунта задан индивидуальный лимит запросов, он может только снизить RPM уровня, но не повысить его.
503 overloadedserviceЭто не ваш лимит, а защита сервиса: Retry-After: 2 означает достижение общего лимита для всех аккаунтов, а Retry-After: 1 — что один из серверов занят. Повторите запрос после паузы.
429 from a providerupstreamerror.cause = supplier_rate_limited означает, что провайдер модели ограничил запрос, а ваш собственный лимит не исчерпан; channel_rate_limited — общий лимит канала провайдера (Retry-After: 10, ничего не было отправлено).

Повторные попытки запросов

Для повторяемого ответа сначала используйте Retry-After, если он присутствует. Без этого заголовка не считайте никакой 429 или 503 автоматически повторяемым: проверьте статус HTTP и публичный error.type, устраните непреодолимую причину и применяйте ограниченный backoff только для временной ошибки.

import time, requests

def call_with_retry(url, headers, payload, max_retries=5):
    for attempt in range(max_retries):
        r = requests.post(url, headers=headers, json=payload)
        if r.status_code == 429:
            # honor Retry-After, otherwise exponential backoff
            wait = int(r.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        return r
    return r
Ошибки и лимиты GetVibe API — 401, 402, 403, 429 | GetVibe API