Ошибки API
Формат ошибки, коды ответов и стабильные строковые коды, по которым программа отличает один отказ от другого, и порядок повторных попыток.
Формат ошибки
Любой отказ приходит с кодом HTTP не ниже 400 и телом в формате OpenAI, поэтому библиотеки разбирают его сами.
{
"error": {
"message": "Модель «такой-модели-нет» не найдена. Список: GET /v1/models",
"type": "invalid_request_error",
"param": "model",
"code": "model_not_found"
}
}
Опирайтесь на code. Коды стабильны, а текст в message написан для человека и может меняться. Поле param называет параметр запроса, из-за которого возник отказ, а при остальных ошибках содержит null. В заголовке x-request-id приходит номер запроса. Он нужен в обращении к поддержке.
Ключ и доступ
| HTTP | code | Причина и действие |
|---|---|---|
| 401 | invalid_api_key | Ключ не передан или неверен. Проверьте заголовок Authorization |
| 401 | api_key_revoked | Ключ отозван. Создайте новый |
| 401 | api_key_expired | Срок действия ключа истёк. Создайте новый |
| 403 | api_key_blocked | Ключ закрыла администрация. Напишите в поддержку |
| 403 | ip_not_allowed | Адрес отправителя не входит в список ключа. Сообщение называет адрес, который увидел epicai |
| 403 | account_suspended | Аккаунт заблокирован или удалён |
| 403 | email_not_confirmed | Почта аккаунта не подтверждена |
| 403 | organization_inactive | Организация или участие сотрудника не активны, ключ организации не работает |
| 403 | model_not_allowed | Модель не входит в список разрешённых для ключа |
Баланс и лимиты
| HTTP | code | Причина и действие |
|---|---|---|
| 402 | insufficient_funds | Не хватает TOK на резерв. Пополните баланс или уменьшите max_tokens. У задач с картинками, видео и другими медиа резервируется вся цена задачи. Сообщение называет нужную и доступную суммы |
| 402 | organization_limit_reached | Достигнут лимит расходов организации, сообщение называет какой |
| 429 | rate_limit_exceeded | Превышен предел запросов в минуту. Подождите, сколько указано в Retry-After |
| 429 | too_many_concurrent_requests | Слишком много одновременных запросов ключа. Повторите через 3 секунды или дождитесь ответов |
| 429 | key_day_cap_reached | Исчерпан суточный потолок расхода ключа. Счётчик обнуляется в полночь по Москве |
| 429 | key_month_cap_reached | Исчерпан месячный потолок расхода ключа |
| 429 | too_many_active_tasks | Набрано предельное число задач в работе (по умолчанию 20). Дождитесь завершения любой, пауза указана в Retry-After |
| 429 | too_many_failed_attempts | С вашего адреса пришло слишком много неверных ключей. Подождите, сколько указано в Retry-After |
| 429 | balance_busy | Баланс занят другим запросом. Повторите через секунду |
Ошибки запроса
| HTTP | code | Причина и действие |
|---|---|---|
| 400 | invalid_json | Тело пустое, не JSON или не объект |
| 400 | missing_required_parameter | Нет model, либо messages пуст или не массив |
| 400 | invalid_parameter | Значение поля вне допустимого. В param и тексте названо поле |
| 400 | unsupported_parameter | Параметр не поддерживается (n больше 1, logprobs и другие) |
| 400 | unknown_parameter | В теле есть поле, которого адрес не принимает. Допустимые названы в сообщении |
| 400 | unsupported_parameters | У сочетания параметров и файлов нет цены. Допустимые сочетания в GET /v1/models/{id} |
| 400 | unsupported_model | Текстовые модели запускаются через /v1/chat/completions, остальные через /v1/tasks |
| 400 | unsupported_tool | Инструмент не из семейства function |
| 400 | unsupported_content | Часть сообщения неподходящего вида, либо модель не принимает картинки |
| 400 | invalid_image | Картинка не прошла проверку формата или вендор не смог её получить. Тот же код приходит, если в images картинок больше, чем принимает модель |
| 400 | invalid_input | Входное видео или аудио не прошло проверку по формату, размеру, длительности или числу файлов |
| 400 | prompt_too_long | Текст запроса длиннее предела модели. Предел назван в сообщении и лежит в поле prompt_max описания модели |
| 400 | result_too_large | Готовая картинка слишком велика для response_format = b64_json. Запросите url |
| 400 | content_filter | Фильтр безопасности вендора отклонил запрос |
| 400 | context_length_exceeded | Запрос не помещается в окно контекста модели. Сократите историю |
| 400 | invalid_request | Вендор не принял параметры запроса, в сообщении его пояснение |
| 400 | invalid_source | Источник операции не подходит, причина в message |
| 404 | model_not_found | Такой модели нет в списке. Сверьтесь с GET /v1/models |
| 404 | task_not_found | Такой задачи нет среди задач ваших ключей |
| 404 | not_found | Неизвестный адрес |
| 405 | method_not_allowed | Метод не подходит адресу, в заголовке Allow перечислены допустимые |
| 409 | idempotency_conflict | Idempotency-Key уже использован с другими параметрами. Для новой задачи нужен новый |
| 413 | request_too_large | Тело запроса больше 12 МБ либо присланный файл больше допустимого размера |
Сбои на стороне модели
| HTTP | code | Причина и действие |
|---|---|---|
| 502 | upstream_unreachable | epicai не достучался до вендора |
| 502 | upstream_error | Вендор вернул ошибку |
| 502 | empty_response | Модель вернула пустой ответ |
| 502 | empty_result | Нейросеть завершила задачу без результата |
| 503 | upstream_unavailable | Модель временно недоступна или перегружена |
| 503 | model_unavailable | Модель сейчас недоступна, повторите позже |
| 503 | billing_unavailable | Не удалось поставить резерв токенов |
| 503 | api_disabled | API временно выключено |
| 503 | media_disabled | Задачи с медиа временно выключены, чат работает |
| 503 | task_unavailable | Не удалось создать задачу, резерв не поставлен. Повторите позже |
| 503 | storage_unavailable | Не удалось сохранить входной файл или результат. Повторите запрос |
| 504 | upstream_timeout | Модель не ответила вовремя |
| 500 | internal_error | Сбой на стороне epicai. Сообщите номер из x-request-id в поддержку |
Запрос с ошибкой бесплатен, пока модель ничего не отдала. Поток, который успел отдать часть ответа, оплачивается за эту часть, подробности есть в статье Потоковый ответ.
Ошибка внутри задачи
Принятая сервером задача может закончиться отказом уже у вендора. Создание тогда отвечало 201, а ошибка приходит в самой задаче, со статусом failed и объектом error из полей code и message. Токены за такую задачу не списаны, резерв снят. Адреса в форме OpenAI (/v1/images/generations, /v1/audio/speech, /v1/audio/transcriptions) отвечают той же ошибкой с кодом HTTP из таблицы.
| HTTP в адресах OpenAI | error.code | Причина и действие |
|---|---|---|
| 400 | content_filter | Фильтр безопасности отклонил описание или входной файл |
| 400 | prompt_too_long | Текст длиннее предела модели |
| 400 | input_unavailable | Вендор не смог скачать файл по ссылке. Откройте ссылку без входа или передайте файл в base64 |
| 400 | input_unsupported | Формат или вид входного файла не подходит модели |
| 400 | input_invalid | Размер, разрешение или длительность вне допустимого |
| 400 | invalid_prompt_flags | Midjourney отклонил флаги -- в тексте запроса |
| 413 | input_too_large | Входные файлы слишком велики для нейросети |
| 504 | upstream_timeout | Нейросеть не ответила вовремя |
| 504 | task_timeout | Задача не завершилась за 100 минут и остановлена |
| 502 | upstream_error | Сбой на стороне нейросети |
| 502 | generation_failed | Нейросеть не выполнила запрос, причина не распознана. Измените параметры или повторите |
Что повторять
Ошибки 4xx, кроме 429, повторять бессмысленно, сначала исправьте запрос, ключ или баланс. Ответы 429 и 5xx стоит повторить, соблюдая паузу из заголовка Retry-After, а без него с нарастающей задержкой. Создание задачи повторяйте с тем же Idempotency-Key: двойного запуска и двойной оплаты не будет. Библиотеки OpenAI делают это сами и по умолчанию повторяют запрос до двух раз.
import os
import openai
from openai import OpenAI
client = OpenAI(
base_url="https://epicai.ru/v1",
api_key=os.environ["EPICAI_API_KEY"],
max_retries=2,
)
try:
client.chat.completions.create(
model="такой-модели-нет",
messages=[{"role": "user", "content": "Привет"}],
)
except openai.APIStatusError as e:
print("HTTP:", e.status_code)
print("code:", e.code)
print("message:", e.message)
print("request:", e.response.headers.get("x-request-id"))
except openai.APIConnectionError as e:
print("Нет связи с API:", e)Не нашли ответ?
Посмотрите частые вопросы или напишите в поддержку.