Ошибки API Jev: 401, 422, 429, 529 — причины и решения
API Jev возвращает четыре основных кода ошибок. Два из них лечатся исправлением запроса, ещё два — повтором с задержкой. Разбираем, что означает каждый код, какие исключения бросают SDK TypeSafe и чем отличаются ответы Polza.AI, Vercel и Cloudflare.
Коротко: четыре кода
| Код | Что случилось | Повторять? | Что делать |
|---|---|---|---|
| 401 Unauthorized | Ключа нет или он неверный | Нет | Проверить заголовок Authorization, ключ и адрес площадки |
| 422 Unprocessable Entity | Тело запроса не прошло проверку | Нет | Исправить поле, указанное в ответе |
| 429 Too Many Requests | Превышен лимит запросов или токенов | Да, с задержкой | Экспоненциальная пауза, заголовок Retry-After, меньше параллельных запросов |
| 529 Overloaded | TypeSafe временно перегружен | Да, с задержкой | Экспоненциальная пауза, SDK справится сам |
Ошибки приходят со стандартным HTTP-кодом и JSON-телом. По документации Vercel и Polza.AI, в теле ошибки TypeSafe есть текст message и машиночитаемый тип error_type. Пример из документации Vercel:
{
"message": "questions.refund.type: expected one of 'noul', 'choice', 'score'",
"error_type": "invalid_request"
}
В ответах API есть заголовок x-typesafe-request-id с идентификатором запроса. Сохраняйте его в логах: по нему поддержка найдёт конкретный вызов.
401: ключ не принят
Частые причины:
- нет заголовка
Authorization: Bearer <ключ>или в нём опечатка; - ключ от другой площадки: например, ключ Polza.AI отправлен на
api.typesafe.aiили ключ TypeSafe — в OpenRouter; - ключ отозван. Ключи TypeSafe управляются в консоли
console.typesafe.ai; - в Vercel истёк локальный OIDC-токен: он живёт 12 часов, обновите его командой
vercel env pull; - в Cloudflare у токена нет права Workers AI. Такой токен получает 401 с кодом ошибки 10000.
Python SDK проверяет ключ ещё при создании клиента. Пробелы и переводы строк по краям он обрезает, а пустой ключ, пробелы внутри, управляющие и не-ASCII символы отклоняет с TypeSafeError до отправки запроса. Так ловится, например, кириллическая буква, попавшая в ключ при копировании. Явно переданный пустой ключ не заменяется значением из TYPESAFE_API_KEY.
Быстро проверить ключ можно запросом списка моделей:
curl -i https://api.typesafe.ai/v1/models \
-H "Authorization: Bearer $TYPESAFE_API_KEY"
Если здесь ответ 200, ключ рабочий: проверьте адрес и заголовок в основном запросе. При 401 от сервера Python SDK бросает TypeSafeAuthenticationError, JavaScript SDK — AuthenticationError. Повторять такой запрос бессмысленно.
422: запрос не прошёл валидацию
Сервер отвечает 422, когда тело запроса не проходит проверку: например, не хватает обязательного поля или вопрос описан неверно. В теле ответа указано поле с ошибкой. Проверьте по списку:
- есть все три обязательных поля:
model,state,questions; - у каждого вопроса есть
type(noul,choiceилиscore) иinstructions; - у
choiceполеcriteria— объект «вариант: описание», вариантов не больше 255, описание может бытьnull; - у
scoreполеcriteria— упорядоченный массив минимум из двух и максимум из десяти уровней; - у
noulполеcriteriaнеобязательно, а в нём допустимы только ключиtrueиfalse.
Обратите внимание на две ловушки. Первая — тип boolean вместо noul. Так вопрос «да/нет» называется в эндпоинте оценки Vercel, и при переносе кода между форматами его легко перепутать: пример ошибки выше как раз про это. Вторая — criteria у score в виде объекта с числовыми ключами. Этот формат убрали в SDK версии 0.6.0: теперь уровни передаются упорядоченным списком.
Часть проверок Python SDK делает локально: пустой словарь вопросов или пустой список уровней у score даст TypeSafeError без запроса к серверу. Ответ 422 от сервера превращается в TypeSafeUnprocessableEntityError, в JavaScript — в UnprocessableEntityError. Повтор не поможет, нужно исправить запрос.
Отдельно следите за размером. Лимит модели — 64 000 токенов на весь запрос и 32 000 на state вместе с самым длинным вопросом. Какой код вернёт TypeSafe при превышении, документация не уточняет. Polza.AI в этом случае отвечает 400.
429: превышен лимит
По документации TypeSafe, у Jev 1.13 два лимита: 1200 запросов в минуту и 250 000 токенов в секунду. Превышение любого из них даёт 429. Компания предупреждает, что лимиты сейчас меняются динамически и без уведомления: спрос большой, мощности добавляются. Повышенные лимиты доступны на индивидуальных и корпоративных тарифах.
Что делать:
- Ждать, а не повторять сразу. Если в ответе есть заголовок
Retry-Afterилиretry-after-ms, подождите указанное время. SDK достают его сами: в Python полеretry_after_msуTypeSafeRateLimitError, в JavaScript —retryAfterMsуRateLimitError. - Ограничить параллельность. Как это сделать в асинхронном коде, показано в статье об асинхронном клиенте на Python.
- Объединять вопросы. Десять вопросов к одному тексту лучше задать одним запросом, а не десятью. Запросов станет меньше, а текст будет оплачен один раз. Подробнее в статье о fan-out запросах.
У площадок-посредников лимиты свои. Например, на бесплатном тарифе Vercel AI Gateway лимиты на модель ниже, чем на платном.
529: TypeSafe перегружен
Код 529 не входит в стандартный набор HTTP, TypeSafe использует его для временной перегрузки. Ваш запрос корректен, повторите его с экспоненциальной задержкой. Python SDK относит 529 к TypeSafeInternalServerError (все ответы 5xx), JavaScript SDK — к InternalServerError. Оба SDK по умолчанию повторяют ответы 500–599, поэтому при короткой перегрузке запрос будет повторён без вашего участия.
Если 529 приходит постоянно и повторы не помогают, это сбой на стороне сервиса. Для важных сценариев держите запасной путь: другую площадку с Jev или отложенную обработку очереди.
Как SDK повторяют запросы
Настройки повторов в двух SDK совпадают по смыслу, различаются только имена:
| Что | Python (RetryPolicy) |
JavaScript (RetryPolicy) |
По умолчанию |
|---|---|---|---|
| Число повторов | max_retries |
maxRetries |
2 |
| Первая пауза | backoff_initial |
backoffInitialMs |
0,5 с, удваивается |
| Максимальная пауза | backoff_max |
backoffMaxMs |
5 с |
| Случайное уменьшение паузы | backoff_jitter |
backoffJitter |
до 25% |
| Какие коды повторять | http_statuses |
httpStatuses |
408, 429, 500–599 |
| Учитывать Retry-After | respect_retry_after |
respectRetryAfter |
да |
Обрывы соединения и таймауты оба SDK тоже повторяют по умолчанию. В Python у RetryPolicy есть общий бюджет времени на вызов, timeout: 30 секунд вместе с паузами. Если следующая пауза не укладывается в бюджет, SDK прекращает попытки и бросает последнюю ошибку. В JavaScript таймаут задаётся на попытку (10 секунд), а ожидание по Retry-After ограничено параметром maxRetryAfterMs (60 секунд).
Обработка ошибок в Python после всех повторов:
from typesafe_sdk import (
Noul,
RetryPolicy,
TypeSafeAPIConnectionError,
TypeSafeAuthenticationError,
TypeSafeClient,
TypeSafeInternalServerError,
TypeSafeRateLimitError,
TypeSafeUnprocessableEntityError,
)
client = TypeSafeClient(retry=RetryPolicy(max_retries=4, backoff_max=10.0, timeout=60.0))
try:
result = client.system_one(
"Верните деньги за двойное списание!",
{"refund": Noul(instructions="Клиент просит вернуть деньги?")},
)
except TypeSafeAuthenticationError:
raise # 401: проверьте ключ и адрес площадки
except TypeSafeUnprocessableEntityError as error:
print("Ошибка в запросе:", error.body) # 422
except TypeSafeRateLimitError as error:
print("Лимит:", error.retry_after_ms, error.request_id) # 429 после всех повторов
except TypeSafeInternalServerError as error:
print("Сбой сервиса:", error.status, error.request_id) # 5xx, включая 529
except TypeSafeAPIConnectionError:
print("Нет соединения или истёк таймаут")
Все HTTP-ошибки наследуются от TypeSafeAPIError: у них есть status, body, headers и request_id. Таймаут (TypeSafeAPITimeoutError) — частный случай ошибки соединения. Подробнее о клиенте — в статье о Python SDK.
Без SDK: повтор вручную
Если вы вызываете API напрямую, повторяйте запрос сами. Минимальный вариант на Python с библиотекой requests:
import os
import random
import time
import requests
URL = "https://api.typesafe.ai/v1/systemone"
RETRYABLE = {408, 429} | set(range(500, 600))
def system_one(payload: dict, max_retries: int = 4) -> dict:
headers = {"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}"}
for attempt in range(max_retries + 1):
response = requests.post(URL, json=payload, headers=headers, timeout=10)
if response.status_code not in RETRYABLE or attempt == max_retries:
response.raise_for_status() # 401 и 422 не повторяем
return response.json()
try:
delay = float(response.headers["Retry-After"])
except (KeyError, ValueError):
delay = min(0.5 * 2**attempt, 5.0) * random.uniform(0.75, 1.0)
time.sleep(delay)
Ошибки шлюзов и агрегаторов
Площадки-посредники добавляют свои коды:
| Площадка | Особенности |
|---|---|
| Polza.AI | Ошибки валидации приходят как 400 вместо 422. Нехватка денег на балансе — 402 (insufficient_balance), недоступность или перегрузка провайдера — 503. Формат ошибки: error.code, error.message, trace_id, а форма TypeSafe дублируется в поле detail |
| Vercel AI Gateway | Ошибки провайдера передаются без изменений. Свои коды шлюза: 401 (ключ или OIDC-токен), 402 (нет кредитов или исчерпан бюджет), 403 (модель вне бесплатного набора, не добавлен способ оплаты или сработало ограничение команды) |
| Cloudflare | Токен без права Workers AI получает 401 с кодом 10000 |
SDK TypeSafe повторяют и 503, так как он попадает в диапазон 500–599. А вот 402 не повторяется: пополните баланс. Как устроены ошибки у российского агрегатора, подробно описано в статье о подключении через Polza.AI.
Что приложить к обращению в поддержку
- идентификатор запроса: заголовок
x-typesafe-request-idили полеrequest_idу исключения, а для Polza.AI —trace_id; - код ответа, тело ошибки и время запроса;
- лог с подробностями. Уровень
debugвключается переменнойTYPESAFE_LOG_LEVEL=debugдо импорта SDK: он запишет заголовки и тела запросов и ответов. Секретные заголовки SDK скрывает, а тела нет, поэтому проверьте лог на персональные данные перед отправкой.
Полный формат запроса и ответа собран в справочнике API Jev.
Частые вопросы
Что значит ошибка 529 в API Jev?
Сервис TypeSafe временно перегружен. Сам запрос корректен, его нужно повторить с экспоненциальной задержкой. Официальные SDK делают это автоматически.
Почему Jev возвращает 422?
Тело запроса не прошло проверку: нет обязательного поля, неверный type вопроса, у choice больше 255 вариантов или у score меньше двух или больше десяти уровней. В теле ответа указано поле с ошибкой.
Сколько запросов в минуту можно отправлять в Jev?
По документации TypeSafe — до 1200 запросов в минуту и до 250 000 токенов в секунду. Превышение любого из лимитов даёт 429. Компания предупреждает, что лимиты сейчас меняются без уведомления.
Повторяет ли SDK Jev запросы сам?
Да. Python и JavaScript SDK по умолчанию делают до двух повторов на кодах 408, 429 и 500–599, учитывают заголовок Retry-After и увеличивают паузу от 0,5 до 5 секунд.
Источники
- TypeSafe Docs — API reference
- TypeSafe Docs — Python SDK: Exceptions
- TypeSafe Docs — Python SDK: Retries
- TypeSafe Docs — Python SDK: Usage
- TypeSafe Docs — Models
- TypeSafe Docs — JavaScript SDK: RetryPolicy
- TypeSafe Docs — JavaScript SDK: TypeSafeClientConfig
- Polza.AI Docs — POST Systemone
- Vercel Docs — TypeSafe API with AI Gateway
- Vercel Docs — AI Gateway FAQ
- Cloudflare AI Gateway docs — REST API