Выведите тело ответа целиком
Не только message. В логах должны быть HTTP-код, type, code и param: без них половина ошибок выглядит одинаково.
Любая ошибка OpenAI приходит в одном формате: объект error с полями message, type, code и param. Разбираем, что в них написано и по какому полю выбирать действие.
Коротко: OpenAI error — это тело ответа с HTTP-кодом 4xx или 5xx, внутри которого лежит объект error с четырьмя полями: message (текст для человека), type (класс проблемы), code (точная причина) и param (какой параметр запроса виноват). Читать нужно не message, а type и code: текст меняется, коды нет.
Поле type принимает пять значений. invalid_request_error — запрос собран неверно, и в param указано, какое поле. authentication_error — ключ не принят: пустой, с опечаткой, отозван или не от этого сервиса. insufficient_quota — деньги кончились, повторять бесполезно. rate_limit_error — слишком часто, повтор через паузу проходит. server_error — сбой на стороне OpenAI, повторять с растущей паузой.
Поле code уточняет: invalid_api_key, model_not_found, context_length_exceeded, unsupported_country_region_territory. Последний код означает, что дело не в ключе и не в запросе, а в стране, откуда пришёл запрос. Официальные SDK превращают всё это в исключения по HTTP-коду, поэтому в Python и Node ловить удобнее по классу, а внутри класса смотреть code.
Ошибки у нас в формате OpenAI, поэтому обработка ошибок в вашем коде не меняется. А unsupported_country из-за России не будет: запросы идут без VPN.
https://api.kosareva.cloud/v1, ключ из кабинетаfrom openai import OpenAI client = OpenAI( api_key="ВАШ_API_КЛЮЧ", base_url="https://api.kosareva.cloud/v1", ) response = client.chat.completions.create( model="gpt-5-6", messages=[{"role": "user", "content": "Привет!"}], stream=True, )
import OpenAI from "openai"; const client = new OpenAI({ apiKey: "ВАШ_API_КЛЮЧ", baseURL: "https://api.kosareva.cloud/v1", }); const response = await client.chat.completions.create({ model: "gpt-5-6", messages: [{ role: "user", content: "Привет!" }], stream: true, });
curl https://api.kosareva.cloud/v1/chat/completions \ -H "Authorization: Bearer ВАШ_API_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-5-6","messages":[{"role":"user","content":"Привет!"}],"stream":true}'
пустая переменная окружения, ключ с пробелом или кавычкой, ключ от другого сервиса. Тип authentication_error, code invalid_api_key.
запрос пришёл с российского IP. Тип invalid_request_error или permission_error, code unsupported_country_region_territory, HTTP 403.
предоплата исчерпана или карта не привязана. Тип insufficient_quota, HTTP 429, повтор не поможет.
неверное имя модели, лишний параметр, слишком длинный контекст. Тип invalid_request_error, HTTP 400 или 404, в param имя поля.
больше запросов или токенов в минуту, чем разрешает уровень аккаунта. Тип rate_limit_error, HTTP 429.
сбой у OpenAI. Тип server_error, HTTP 500–503, помогает повтор.
| Текст ошибки | type / code | Что делать |
|---|---|---|
| Incorrect API key provided | authentication_error / invalid_api_key | Проверить переменную окружения, пересоздать ключ, убедиться, что ключ от нужного сервиса. |
| Unsupported country, region, or territory | invalid_request_error / unsupported_country_region_territory | Ключ и запрос в порядке, закрыт регион. Нужен другой адрес API, а не другой ключ. |
| You exceeded your current quota | insufficient_quota | Пополнить баланс у поставщика. Повторы бесполезны. |
| Rate limit reached for model | rate_limit_error | Повторить через паузу, уважать Retry-After, сократить параллельность. |
| The model `x` does not exist | invalid_request_error / model_not_found | Проверить точное имя модели в списке /v1/models и права ключа на неё. |
| This model's maximum context length is N tokens | invalid_request_error / context_length_exceeded | Укоротить историю сообщений или уменьшить max_tokens. |
Тексты message OpenAI меняет без предупреждения. Код в поле code и тип в поле type стабильны, ориентируйтесь на них.
Не только message. В логах должны быть HTTP-код, type, code и param: без них половина ошибок выглядит одинаково.
В SDK на Python и Node у каждого HTTP-кода свой класс: BadRequestError 400, AuthenticationError 401, PermissionDeniedError 403, NotFoundError 404, RateLimitError 429, InternalServerError 5xx. Сетевые проблемы — APIConnectionError и APITimeoutError, у них тела ответа нет.
authentication_error и insufficient_quota — остановиться и чинить ключ или баланс. rate_limit_error и server_error — повторить с паузой. invalid_request_error — исправить запрос по полю param.
Если curl отвечает списком моделей, ключ и адрес рабочие, и проблема в коде приложения.
Свой лог приложения с полным телом ответа и панель поставщика, где видны отклонённые запросы по ключу. Если в панели запроса нет вовсе, он не дошёл: проблема в сети, прокси или base URL.
Исключение содержит status_code и body; в Node это error.status и error.error. Не оборачивайте в общий except без вывода body.
Редактор показывает message, а type и code часто скрывает. Повторите тот же запрос через curl, чтобы увидеть полное тело.
В выводе ноды есть сырой ответ сервера: разверните его, поле error.code там на месте.
Обёртки пробрасывают исключения OpenAI SDK как есть, ловите те же классы.
Ключ выдаётся в панели OpenAI, но из России регистрация, оплата и запросы закрыты, поэтому даже правильный ключ отвечает unsupported_country_region_territory. Подробнее на странице о получении ключа.
Первое — ключ не узнан, HTTP 401. Второе — ключ узнан, но денег нет, HTTP 429. Чинятся в разных местах: ключ и баланс.
Оно приходит с HTTP 429 и попадает в RateLimitError. Отличать нужно по полю code внутри исключения, иначе цикл повторов будет бить в пустой счёт.
rate_limit_error и server_error — с растущей паузой. insufficient_quota, authentication_error и invalid_request_error повторять бесполезно: чините баланс, ключ или сам запрос.
Запрос длиннее окна модели. Укоротите историю сообщений или уменьшите max_tokens: в сумме они должны уложиться в контекст модели.
OpenAI-совместимый адрес, оплата в рублях, ключ сразу после регистрации. Пополнение картой от 50 ₽.