Ошибка model_retired: модель сняли с обслуживания

Модель, которая работала вчера, сегодня отвечает 400 с кодом model_retired. Разбираем, что это значит и как обработать это в коде, а не руками.

4 мин · · Обновлено · ошибки

Каталог моделей не статичен: провайдеры выпускают новые версии и снимают старые с обслуживания. Когда это происходит с моделью, которую вы указали в запросе, ответ приходит не как model_not_found, а как отдельная ошибка model_retired — и в ней сразу написано, чем заменить.

Как выглядит ответ

bash
{
  "error": {
    "message": "Модель 'gpt-5.4' снята с обслуживания. Используйте 'gpt-5.6-sol'",
    "code": "model_retired"
  }
}

HTTP-статус — 400. Это важно отличать от других кодов, с которыми model_retired иногда путают:

  • 404 model_not_found — опечатка в названии, модели с таким id никогда не было или её id набран неверно.
  • 503 provider_unavailable — модель в каталоге есть, но провайдер временно недоступен (авария, технические работы).
  • 503 model_disabled — модель выключена в каталоге Zukko (так, например, отвечает claude-opus-4.6). Замены в ответе нет — выберите её сами по GET /v1/models.
  • 400 model_retired — модель окончательно выведена из каталога. Она не вернётся, и в сообщении сразу указана замена.

Почему это не баг на вашей стороне

Если вчера запрос с model: "gpt-5.4" работал, а сегодня падает с model_retired, конфиг никто не трогал — обновился каталог на сервере. Это нормальная часть жизненного цикла моделей: старые версии GPT, Claude или GLM со временем заменяются более новыми, и провайдер прекращает их поддержку.

Актуальный список моделей всегда можно получить без ключа:

bash
curl https://api.zukko.pro/v1/models

Расширенная версия с лимитами и ценами — GET /v1/models/info, тоже без ключа.

Не гадайте замену — она уже в ответе

Частая ошибка — увидеть model_retired и начать перебирать похожие по названию модели вручную. Не нужно: сообщение об ошибке буквально содержит правильный id. Проще всего вытащить его регуляркой прямо из текста сообщения.

Python:

bash
import re
import requests

def call_model(model_id, messages):
    resp = requests.post(
        "https://api.zukko.pro/v1/chat/completions",
        headers={"Authorization": "Bearer fetch_ваш_ключ"},
        json={"model": model_id, "messages": messages},
    )
    if resp.status_code == 400:
        data = resp.json()
        if data.get("error", {}).get("code") == "model_retired":
            match = re.search(r"Используйте '([^']+)'", data["error"]["message"])
            if match:
                new_model = match.group(1)
                return call_model(new_model, messages)
    resp.raise_for_status()
    return resp.json()

То же самое на JS, если вы работаете через Anthropic-совместимый путь /v1/messages:

bash
async function callModel(modelId, body) {
  const resp = await fetch("https://api.zukko.pro/v1/messages", {
    method: "POST",
    headers: {
      "Authorization": "Bearer fetch_ваш_ключ",
      "anthropic-version": "2023-06-01",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ ...body, model: modelId }),
  });

  if (resp.status === 400) {
    const data = await resp.json();
    if (data.error?.code === "model_retired") {
      const match = data.error.message.match(/Используйте '([^']+)'/);
      if (match) return callModel(match[1], body);
    }
  }
  return resp.json();
}

Автоматическое переключение удобно для фоновых сервисов, где нет человека, читающего логи в реальном времени. Для интерактивных инструментов (Claude Code, Cursor) правильнее один раз обновить id модели в конфиге, а не переключаться на лету при каждом запуске.

Где чаще всего остаётся старый id

  • Захардкоженный model в скрипте или CI-пайплайне, который никто не трогал месяцами.
  • .env файл с переменной вроде LLM_MODEL=gpt-5.4, скопированной из старого проекта.
  • Конфиг Claude Code / Cursor, где модель один раз выбрали при настройке и забыли.

Если у вас несколько мест с захардкоженным id, model_retired в логах — сигнал пройтись по всем и свериться с GET /v1/models.

Что не стоит делать

Не пытайтесь угадать замену по смыслу названия («сняли gpt-5.4, значит возьму gpt-5.6-luna — та же линейка»). Разные модели линейки GPT-5.6 (sol и luna) — не взаимозаменяемые синонимы, у них разная цена ($0.30 и $0.10 за 1M токенов). Сервер в сообщении model_retired называет ту замену, которая реально соответствует снятой модели, — используйте именно её, а не первую похожую по названию.

Если после замены модели поведение приложения ощутимо изменилось (другая длина ответов, другой стиль), это ожидаемо — вы вызываете другую модель. В таком случае стоит проверить промпт и max_tokens, а не искать ошибку в интеграции.

Что вообще сейчас есть в каталоге

Если замена в сообщении об ошибке кажется незнакомой, полезно держать в голове актуальный список текстовых моделей, а не только ту, с которой вы работали раньше:

  • Claude: claude-opus-5-5 (Claude Opus 5.5, контекст 1M), claude-sonnet-5 (контекст 1M).
  • GPT-5.6: gpt-5.6-sol и gpt-5.6-luna (контекст 1M).
  • GLM: glm-5.3 и glm-5.3-flash (контекст 128K, без vision).

Актуальный список — GET https://api.zukko.pro/v1/models. Обратите внимание: у моделей Claude и GPT контекст 1 000 000 токенов и приём изображений, а у GLM — 128K и без vision, так что при замене на GLM логику вокруг изображений и длинного контекста нужно проверить. Генерация изображений через Zukko временно недоступна.

Если в проекте упоминаются модели вроде claude-3.5, gpt-4o или claude-3-opus — это не то же самое, что снятие с обслуживания внутри каталога: таких id в каталоге никогда не было, и model_retired в их случае не появится, будет обычный model_not_found. Мигрировать с таких названий нужно вручную, сверяясь со списком выше, а не ждать подсказки в тексте ошибки.

Итог в одну строку

model_retired — не ошибка настройки, а сигнал, что каталог обновился. Замена уже указана в message, дело за тем, чтобы код её подхватил, а не человек вручную правил конфиг при каждом объявлении о выводе модели из эксплуатации.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.