Ответ модели обрывается на середине — причины
Ответ обрывается на полуслове. Причин четыре, и различаются они по одному полю в ответе API.
2 мин · · Обновлено · ошибки · стриминг · надёжность
Обрыв ответа выглядит одинаково во всех случаях, но причин четыре, и лечатся они по-разному. Различить их можно по полю finish_reason (в OpenAI-совместимом формате) или stop_reason (в Anthropic-совместимом).
Упёрлись в max_tokens
Признак: finish_reason равен length.
Модель не закончила мысль, а просто исчерпала лимит на длину ответа. Ответ при этом валидный и полностью оплаченный.
Решение очевидное — поднять max_tokens. Значение по умолчанию у многих SDK маленькое, а некоторые клиенты вообще ставят единицы сотен. Для длинных ответов ставьте с запасом, но помните, что зарезервированное место вычитается из контекстного окна.
Таймаут на стороне клиента
Признак: ответ обрывается всегда примерно на одной и той же секунде, а finish_reason вы не видите вовсе, потому что ответа целиком не было.
HTTP-клиенты по умолчанию ждут ответ ограниченное время — часто 30 или 60 секунд. Длинная генерация в это не укладывается.
Два решения. Первое: поднять таймаут клиента до нескольких минут. Второе, лучше: включить потоковую передачу. При стриминге данные идут непрерывно, и соединение не выглядит зависшим.
Оборванный стрим
Признак: работали через стриминг, часть текста пришла, потом поток просто закончился без завершающего события.
Обычно это разрыв сети или прокси, закрывший долгое соединение. Клиент при этом часто не сообщает об ошибке — он получил валидные данные, просто меньше, чем ожидалось.
Проверяйте, что поток завершился штатно: в OpenAI-формате это data: [DONE], в Anthropic-формате — событие message_stop. Если его нет, ответ неполный, и это нужно обрабатывать как ошибку, а не как результат. Учтите при повторе: обрыв стрима не останавливает списание — шлюз дочитывает ответ провайдера и списывает всю генерацию, так что повторный запрос оплачивается заново.
Прокси с буферизацией
Признак: стриминг включён, но текст приходит не постепенно, а одним куском в конце. Либо не приходит вовсе при долгой генерации.
Промежуточный прокси или обратный прокси копит ответ вместо того, чтобы отдавать по мере поступления. Для nginx лечится proxy_buffering off на нужном location. Если между вами и API есть корпоративный прокси, дело может быть в нём.
Что проверить первым
Посмотрите finish_reason. Если там length — вопрос закрыт, поднимайте лимит. Если поля нет вовсе, значит ответ не дошёл целиком, и дальше разбираться нужно с таймаутами и стримом, а не с параметрами запроса.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Ключи OpenAI API в открытом доступе: почему ими нельзя пользоватьсяОткуда берутся «бесплатные» ключи на GitHub, почему пользоваться ими опасно и для вас, и для владельца, и как защитить собственный ключ от такой же утечки.
- Ошибки GLM API: почему не работает запрос и как это исправитьНеверный id модели, переполненный контекст 128K, ключ, баланс, лимиты: типичные причины ошибок GLM API и быстрый способ найти свою.
- This organization has been disabled в Claude API: что это и как продолжитьКлюч Anthropic внезапно отвечает «organization has been disabled». Объясняем, что это за ошибка, что проверить и как перенести SDK и Claude Code на другой провайдер.
- JetBrains AI Assistant не работает: причины и обходные путиAI Assistant не активируется, молчит или недоступен в отдельных файлах. Разбираем причины по документации JetBrains и подключаем свои модели через шлюз.