ток

Документация / Ошибки

Коды ошибок

Ошибка — это настоящий HTTP-статус и JSON вида {"error": {"message", "type", "code"}}. Пока шлюз не начал отвечать, отказ приходит именно так; у потока есть одно исключение, и оно описано ниже.

HTTP/1.1 402 Payment Required
Content-Type: application/json

{
  "error": {
    "message": "insufficient credits: balance 0.012000 USD can only afford 17 tokens, request needs 2048",
    "type": "no_credit",
    "code": "insufficient_credits"
  }
}

Разбирайте code — он машинный и стабильный. Поле message человеческое: часть текстов приходит по-русски, часть от вендора, и полагаться на него в коде не стоит. Исключение одно: текст 402 содержит фразу «can only afford N tokens» — по ней клиент понимает, на сколько уменьшить max_tokens, чтобы остатка хватило.

Статусы и коды

400
bad_request
invalid_request · unknown_model · no_route · context_length_exceeded · content_filter · upstream_400 — запрос не выполнить как он есть.
401
unauthorized
unauthorized — ключа нет, он неизвестен или отозван.
402
no_credit
insufficient_credits — на счёте не хватает даже на этот запрос. Ничего не списано.
403
not_allowed
key_paused · key_blocked · org_suspended · alias_not_allowed · cost_cap.
408
timeout
ttft_timeout · idle_timeout · deadline — модель не начала, перестала или не успела ответить.
409
conflict
idempotency_in_flight — запрос с таким Idempotency-Key ещё выполняется.
413
bad_request
body_too_large — тело больше разрешённого.
429
rate_limit
key_rpm · key_streams · spend_limit_exceeded · upstream_rate_limited. Всегда с Retry-After.
502
upstream_failed
transport · capacity · empty · upstream_auth · upstream_credit · interrupted · internal — сломалось на нашей стороне или у вендора.
503
no_healthy_route
Ни один маршрут алиаса сейчас не отвечает. С Retry-After; повтор имеет смысл.
503
unavailable
auth_unavailable — не отвечает наша проверка ключа. Другой type, чем у соседней строки: разбирайте code.

Промах мимо API — это тоже честный ответ, а не HTML: несуществующий путь под /v1 даёт 404 not_found, а неверный метод — 405 method_not_allowed.

402 — кончились деньги

Запрос не выполняется и не списывается ничего. Пополните счёт или уменьшите max_tokens до числа из текста ошибки. Автопополнение включается в кабинете.

Что повторять

429 и 503 — повторяйте после Retry-After; 502 тоже может его принести, и тогда он важнее вашей выдержки. 408 и 502 без заголовка — повторяйте с нарастающей паузой. 400, 401, 402 и 403 повторять бессмысленно: изменится не результат, а только счётчик запросов.

Ошибка посреди потока

Точка невозврата — первая дельта с текстом. После неё статус уже 200, и об обрыве говорит последний кадр потока: в нём есть error, есть usage, и cost в нём нулевой.

Есть и второй способ получить ошибку под двухсотым, и на него стоит закладываться при stream: true. Если ни один маршрут не начал отвечать за silence_budget (настройка шлюза, десятки секунд), шлюз всё равно открывает поток: отдаёт 200 с заголовками SSE и шлёт keepalive, чтобы клиент не отвалился по таймауту. Дальше лестница может закончиться ничем — и тогда придёт кадр data: {"error": …} без единого кадра с текстом и без кадра usage, а следом [DONE]. Двухсотый сам по себе не значит, что ответ состоялся: смотрите на кадры.

import os

from openai import OpenAI

client = OpenAI(
    base_url="https://ai.globall.dev/v1",
    api_key=os.environ["TOK_API_KEY"],
)

try:
    r = client.chat.completions.create(
        model="anthropic/claude-haiku-5.5",
        messages=[{"role": "user", "content": "Привет"}],
        max_tokens=64,
    )
except Exception as e:
    # e.status_code — статус, e.body["error"]["code"] — машинный код,
    # e.response.headers["X-Request-Id"] — что назвать в поддержке.
    print(e.status_code, e.body["error"]["code"])
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://ai.globall.dev/v1",
  apiKey: process.env.TOK_API_KEY,
});

try {
  await client.chat.completions.create({
    model: "anthropic/claude-haiku-5.5",
    messages: [{ role: "user", content: "Привет" }],
    max_tokens: 64,
  });
} catch (e) {
  // e.status — статус, e.error.code — машинный код,
  // e.headers["x-request-id"] — что назвать в поддержке.
  console.log(e.status, e.error?.code);
}
curl -i https://ai.globall.dev/v1/chat/completions \
  -H "Authorization: Bearer $TOK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-5.5",
    "messages": [{"role": "user", "content": "Привет"}],
    "max_tokens": 16
  }'