Перейти к основному содержанию

Ошибка Gemini «Requests ending with a model turn»: как исправить

С Gemini 3.6 Flash и в Gemini 4 Argon API возвращает 400, если последний ход в contents имеет role model. Закончите запрос ходом user, повтор не поможет.

LaoZhang AI TeamОпубликовано10 мин чтения
Содержание
Ошибка Gemini 400 Requests ending with a model turn: ход model в конце запроса даёт 400, новый ход user в конце той же истории даёт 200, после functionCall нужен functionResponse

Ошибка 400 INVALID_ARGUMENT: Requests ending with a model turn are not supported. означает, что Google получил запрос, в котором последний непустой ход в массиве contents имеет role model, то есть принадлежит модели (в формате OpenAI это сообщение assistant). Правило Google объявил в описании изменений Gemini 3.6 Flash: оно действует для Gemini 3.6 Flash, Gemini 3.5 Flash-Lite и «всех следующих моделей», поэтому под него попадают и Gemini 3.7/3.8 Flash, и gemini-4-argon. Предзаполнение ответа (prefill) больше не поддерживается.

Исправляется это формой запроса: последним в contents должен идти ход user. Уберите prefill и сохранённый в конце истории ответ модели или добавьте после него новое сообщение пользователя. Если последним стоит functionCall, отправьте ход user с functionResponse. Указания вроде «без вступления» перенесите в systemInstruction, а принудительный JSON — в структурированный вывод с JSON schema. Если ошибку выдаёт готовый инструмент, обновите его: в Gemini CLI исправления вошли в v0.65.0. Повторять тот же запрос бесполезно, это ошибка запроса, а не перегрузка.

Есть одна ловушка. То, что в интерфейсе последним стоит ваше сообщение, не доказывает, что запрос к Google заканчивается на user: prefill, функции продолжения, преобразование истории, расширения, прокси и SDK могут дописать или переставить ходы. Смотреть нужно на тело запроса, которое реально уходит в API, а не на окно чата.

Что значит «Requests ending with a model turn are not supported»

Google проверяет только конец запроса: если последний непустой ход в contents принадлежит модели, API возвращает HTTP 400. Раньше так делали намеренно, чтобы модель «продолжила» заготовленное начало ответа, например Translation: или {. Начиная с Gemini 3.6 Flash это запрещено, а замену Google называет прямо: system_instruction или структурированный вывод (Structured outputs). На странице миграции Gemini 4 Argon это правило отдельно не повторяется, но формулировка «all future Gemini model releases» распространяется и на Argon.

Старые модели под правило не попадают: на LINUX DO 22 июля 2026 года писали, что на Gemini 3.5 Flash prefill ещё работает, а на 3.6 Flash уже нет. Возврат к старой модели может временно снять ошибку, но не исправляет запрос.

Текст ошибки встречается в трёх вариантах. Чаще всего это короткая форма из заголовка. В ответах AI Studio, у прокси и в трекере Google по Android Studio встречается длинная: Requests ending with a model turn are not supported unless the last part is a function response. Она подсказывает исключение: ход, который заканчивается результатом функции, допустим. Прокси оборачивают текст в PROXY ERROR 400, а OpenRouter показывает Provider returned error, и исходное сообщение Google лежит в поле error.metadata.raw.

Какой у вас случай: шесть причин, по которым запрос кончается ходом model

Причину проще всего определить по моменту, когда появляется ошибка: на первом же запросе, после отмены или перебивания, после вызова инструмента или только при подсчёте токенов. В таблице собраны случаи из отчётов разработчиков с июля по октябрь 2026 года.

ПричинаКак проявляетсяЧто исправить
Prefill: в конец запроса добавлен заготовленный ход modelПадает каждый запрос, включая первый; на 3.5 Flash и старше то же работалоУбрать prefill; формат задать через systemInstruction или JSON schema
История кончается сохранённым ответом моделиОшибка после /rewind, прерванного потока, Ctrl-C, перебивания голосом, после неупорядоченно сохранённого шага; новое сообщение пользователя «лечит» сессиюПеред отправкой добавить новый ход user или отрезать хвостовой ход model
Последний ход — functionCall модели без ответа инструментаОшибка сразу после того, как модель вызвала функциюВыполнить функцию и отправить ход user с functionResponse, сам ход модели вернуть без изменений
Результат инструмента и дополнительный текст в одном ходе userНа Vertex AI — 400, когда после результата инструмента приложение вставляет напоминание, заметку или реплику пользователяДержать functionResponse последним в своём ходе или вынести текст в отдельный ход user
Изображение в результате инструментаОшибка на каждом шаге сразу после чтения .png или анализа картинки, текстовые шаги проходятВернуть результат инструмента текстом, изображение передать следующим сообщением пользователя
countTokens по истории, которая кончается ответом моделиПодсчёт токенов падает или показывает 0, а генерация работаетСчитать историю до последнего хода user или брать usageMetadata.promptTokenCount из ответа

Случай с результатом инструмента и текстом показывает, что одна и та же история может пройти через одного посредника и не пройти через другого. В трекере агента senpi (issue #3633) 18 октября 2026 года для Gemini 4 Argon на Vertex замерили по одной переменной: последний ход user вида [functionResponse] даёт 200, [functionResponse, text] даёт 400, а [text, functionResponse] снова 200. 28 октября другой участник повторил это на gemini-4-argon через LiteLLM 1.101.0 и Google Cloud Express: когда результат инструмента и текст разнесли в два отдельных хода, запрос прошёл. Та же форма описана в langchain-google #1995, где интеграция vertexai сливает ToolMessage и следующий HumanMessage в один ход user.

Проверка 29 октября 2026 года: какие формы запроса к gemini-4-argon прошли

29 октября 2026 года, с 03:00 до 03:05 UTC, запросы к gemini-4-argon отправлялись через нативный эндпоинт Gemini generateContent на laozhang.ai: REST без SDK, thinkingLevel: low, и в каждом запросе менялась ровно одна деталь истории. Все ответы 200 пришли с modelVersion: gemini-4-argon, все ответы 400 содержали тот же текст ошибки, что и у Google.

Примечание: laozhang.ai — наш собственный сервис; его цены — наши тарифы, а не независимое сравнение.

Содержимое contents (последний элемент справа)Результат
[user]200
[user, model "Rain"], prefill400, при повторе в 03:13 UTC тоже 400
[user, model, user, model], история сохранена сразу после ответа400
Та же история без последнего хода model, то есть с новым user в конце200
[user] и объявленный инструмент200, модель вернула functionCall
[user, model(functionCall)], ответа инструмента ещё нет400
[user, model(functionCall), user[functionResponse]]200
[user, model(functionCall), user[functionResponse, text]]200

Главное в таблице — пара из третьей и четвёртой строк: одна и та же история даёт 400 с ответом модели в конце и 200, когда последним стоит новый ход пользователя. Последняя строка расходится с отчётами о Vertex, где та же форма получала 400. Это зависит от того, как конкретный сервис собирает запрос к Google, поэтому ни один из двух результатов не стоит переносить на другие пути доступа.

Проверка gemini-4-argon 29 октября: шесть вариантов contents, где ход model в конце даёт 400, а та же история с новым ходом user в конце даёт 200

Выборка небольшая: один эндпоинт, один день, по одному запуску на форму (prefill — два). Тело ошибки на этом пути имеет вид {"error":{"message":"…","type":"upstream_error","code":400}}, тогда как сам Google отвечает с полем "status": "INVALID_ARGUMENT". Формы [text, functionResponse], два раздельных хода user, а также замены prefill на systemInstruction и JSON schema в выборку не вошли. Для них ниже приведены рекомендация Google и отчёты о Vertex.

Как исправить запрос: закончить ходом user и убрать prefill

Начните с того, чтобы увидеть настоящий запрос. Включите журналирование тела запроса в SDK или в прокси и найдите последний элемент contents с непустыми parts. Если это model, нужное исправление зависит от того, что в нём лежит. Простая проверка перед отправкой ловит ошибку раньше, чем её вернёт API:

python
def last_turn_role(contents):
    for turn in reversed(contents):
        if turn.get("parts"):
            return turn["role"]
    return None

if last_turn_role(contents) == "model":
    raise ValueError("contents заканчивается ходом model: Gemini вернёт 400")

Если в конце стоит заготовленное начало ответа, уберите его и перенесите смысл в инструкции. Для указаний о стиле и формате Google рекомендует systemInstruction:

json
{
  "systemInstruction": {"parts": [{"text": "Выведи только перевод, без вступления."}]},
  "contents": [
    {"role": "user", "parts": [{"text": "Translate 'Hello world' to Spanish."}]}
  ]
}

Если prefill нужен был, чтобы ответ начинался с {, задайте структурированный вывод в generationConfig: "responseMimeType": "application/json" и схему в "responseJsonSchema", как описано в руководстве Google по структурированному выводу в generateContent. Тогда модель вернёт JSON без заготовки. Если же prefill служил для продолжения обрезанного длинного ответа, причину обрыва нужно искать в finishReason. Об этом подробно в статье Gemini 4 Argon API: доступ, finish_reason и обрыв ответа.

Если история кончается сохранённым ответом модели после отмены, перемотки или перебивания, не отправляйте её в таком виде. Добавьте новый ход user с тем, что вы хотите получить дальше, или отрежьте хвостовой ход model, если он был прерван и не нужен. После functionCall выполните функцию и отправьте ход user с functionResponse. Ход модели с вызовом функции возвращайте ровно в том виде, в каком он пришёл, вместе с thoughtSignature. Google требует передавать подписи размышлений в многоходовых запросах, поэтому удалять или подделывать их нельзя.

Если после результата инструмента нужно добавить текст, а запрос идёт через Vertex AI, держите functionResponse последним в своём ходе или вынесите текст в отдельный ход:

json
[
  {"role": "model", "parts": [{"functionCall": {"name": "get_weather", "args": {"city": "Paris"}}, "thoughtSignature": "…как пришло…"}]},
  {"role": "user", "parts": [{"functionResponse": {"name": "get_weather", "response": {"temp_c": 14}}}]},
  {"role": "user", "parts": [{"text": "Ответь одним предложением."}]}
]

Порядок частей в ходе user с результатом инструмента: на Vertex AI вариант functionResponse, затем text даёт 400, в нашей проверке он дал 200; вариант text, затем functionResponse и два отдельных хода user проходят по отчётам о Vertex AI

Изображение из результата инструмента передайте так же отдельно: результат инструмента текстом, а картинку следующим сообщением пользователя. В hermes-agent #139313 именно такой вариант через OpenRouter и google/gemini-4-argon дал 200, а результат инструмента с картинкой в конце запроса давал 400.

Автоматический повтор здесь не нужен. В руководстве Google по устранению неполадок Gemini API повторять советуют только временные ошибки 429, 408 и 5xx, а 400 — это ошибка в самом запросе, и тот же запрос снова получит 400. Мейнтейнер senpi 20 октября 2026 года тоже попросил считать этот 400 ошибкой запроса, а не поводом для паузы или переключения на запасную модель. Если в вашем коде 400 запускает цикл повторов, как в livekit agents-js #2108, агент просто замолкает.

Почему countTokens на Gemini 4 Argon даёт 400

Об этом сообщил мейнтейнер плагина Obsidian Gemini Scribe allenhutchison в obsidian-gemini #1708 27 октября 2026 года. С моделью gemini-4-argon вызов models.countTokens на первом ходе новой сессии вернул 400 INVALID_ARGUMENT с обрезанным в журнале текстом Requests ending wi…are not supported., а тот же сценарий с gemini-flash-latest проходил. По версии автора, сразу после сохранения ответа история сессии кончается ходом модели, и Argon отклоняет countTokens с таким contents. Сам автор помечает это как гипотезу, а результаты generateContent из таблицы выше с ней согласуются, хотя и не доказывают её. Ошибка в плагине не роняла сессию, но счётчик токенов и порог сжатия контекста получали 0.

Исправление, которое предлагает автор, — считать токены до последнего хода user или добавлять в конец ход user. Вторая задокументированная возможность — вообще не вызывать подсчёт для уже отправленной истории: usageMetadata.promptTokenCount приходит в каждом ответе generateContent и ничего не стоит.

python
def contents_for_count(contents):
    last_user = max(i for i, t in enumerate(contents) if t["role"] == "user")
    return contents[: last_user + 1]

client.models.count_tokens(model="gemini-4-argon", contents=contents_for_count(history))

Сам countTokens для Argon поддерживается: в документации Firebase AI Logic о подсчёте токенов gemini-4-argon стоит первым в списке моделей, вызов бесплатный, квота 3000 запросов в минуту, а в подсчёт входят системные инструкции и инструменты. Если вы работаете через шлюз, сначала убедитесь, что он вообще пропускает :countTokens. На том же шлюзе, что и в проверке выше, запрос к /v1beta/models/gemini-4-argon:countTokens 29 октября 2026 года вернул 400 unsupported action: countTokens независимо от того, чем кончалась история. Это другой 400 от другого слоя, и к правилу о ходе модели он отношения не имеет.

Ошибка в Gemini CLI, opencode, SillyTavern или LangChain: что делать

Если запрос собирает инструмент или библиотека, а не ваш код, исправление нужно искать в нём: обновиться, если фикс уже вышел, или обойти конкретный сценарий, который ставит ход модели в конец. Статусы ниже указаны по состоянию на 29 октября 2026 года.

ИнструментОткуда ход model в концеСтатусЧто сделать
Gemini CLI/rewind, прерванный поток, быстрый Ctrl-C, чтение .png через ReadFile (#29530, #29574)Исправления влиты 7 и 13 октября, оба есть в стабильной v0.65.0 от 20 октябряОбновиться до v0.65.0 или новее
opencodeСлужебное сообщение о лимите шагов добавляется как ответ ассистента (#45359); чтение .png через OpenRouter (#55694)#45359 закрыт, но 15 сентября ошибка повторялась на 1.18.31, слияние PR #55382 не подтверждено; #55694 открытОтправить новое сообщение, после него сессия продолжается
Zoo Code, Kilo CodeZoo Code на Vertex дописывает prefill для вызова инструментов (#1052); в Kilo Code шаги сохранялись не по порядкуОткрытоАвтор отчёта по Zoo Code временно вернулся на gemini-3.5-flash
SillyTavern и другие ролевые фронтендыPrefill ассистента, «продолжить», настройки начала ответа, преобразование истории, расширенияЗависит от пресетаНовый чат, последним — настоящее сообщение пользователя; отключить prefill и продолжение, затем включать по одному
LangChain (langchain-google, vertexai)Результат инструмента и следующий HumanMessage слиты в один ход user (#1995)ОткрытоНе ставить сообщение пользователя сразу за результатом инструмента или разделять их вручную
LiteLLMИстория на Vertex кончается текстовым ответом ассистента (#38537)ОткрытоПеред вызовом убирать хвостовой ответ ассистента или добавлять сообщение пользователя
OpenRouterРезультат инструмента с изображением стоит последним; текст Google виден только в metadata.rawОткрыто в hermes-agent #139313Результат текстом, изображение отдельным сообщением пользователя
instructorПовторный запрос структурированного вывода (reask) заканчивается ходом модели (#2631)ОткрытоАвтор отчёта предлагает max_retries=0 для вызовов Gemini, чтобы reask не запускался

Для Gemini CLI вывод «v0.65.0 и новее» сделан по сравнению тегов на GitHub: оба исправления входят в v0.65.0 и не входят в v0.64.0. Обновить CLI можно командой npm install -g @google/gemini-cli@latest, а подробности установки и входа есть в статье Как установить Gemini CLI: npm, Windows и вход после 18 июня 2026.

В SillyTavern названия пунктов зависят от версии и пресета, поэтому проще проверить сам эффект: начать новый чат, где последним идёт ваше сообщение, и по очереди возвращать prefill ассистента, продолжение ответа и обработку истории, пока ошибка не вернётся. Так советует руководство EvoLink по настройке Gemini в SillyTavern от 16 октября 2026 года.

Ошибка model turn в Gemini: другие вопросы

Это то же самое, что ошибка «role system is not supported»?

Нет. Там API не принимает саму роль сообщения, а здесь роль допустима, но стоит не на своём месте. Про неподдерживаемые роли написано в статье Как исправить API 400 с неподдерживаемой ролью и не сломать системные инструкции.

У Claude тоже запретили prefill?

У Claude похожий запрет на prefill, но у него свой текст ошибки (This model does not support assistant message prefill) и свой список моделей. Подробности в статье Ошибка 400 prefill в Claude: на каких моделях и чем заменить.

Что значит «Function call is missing a thought_signature»?

Это другой 400 у Gemini 3 и новее: в последнем ходе модели вызов функции передан без подписи размышлений. Он появляется, когда приложение пересобирает ход модели вместо того, чтобы вернуть его без изменений; в отчёте senpi от 18 октября 2026 года он встретился на той же истории, что и ошибка о ходе модели.

Какие ещё 400 бывают у Gemini 4 Argon?

По странице миграции Google на 27 октября 2026 года Argon возвращает ошибку на явное кэширование (cachedContents), а temperature, top_p и top_k игнорирует. Это отдельные ограничения Argon, с последним ходом в contents они не связаны.

Источники18

Внешние страницы, на которые ссылается это руководство, в порядке упоминания. Последнее обновление: 29 окт. 2026 г..

  1. 1.в описании изменений Gemini 3.6 Flashai.google.dev/gemini-api/docs/whats-new-gemini-3.6
  2. 2.Gemini 4 Argonai.google.dev/gemini-api/docs/generate-content/latest-model
  3. 3.трекере агента senpi (issue #3633)github.com/code-yeongyu/senpi/issues/3633
  4. 4.langchain-google #1995github.com/langchain-ai/langchain-google/issues/1995
  5. 5.руководстве Google по структурированному выводу в generateContentai.google.dev/gemini-api/docs/generate-content/structured-output
  6. 6.hermes-agent #139313github.com/NousResearch/hermes-agent/issues/139313
  7. 7.руководстве Google по устранению неполадок Gemini APIai.google.dev/gemini-api/docs/troubleshooting
  8. 8.livekit agents-js #2108github.com/livekit/agents-js/issues/2108
  9. 9.obsidian-gemini #1708github.com/allenhutchison/obsidian-gemini/issues/1708
  10. 10.документации Firebase AI Logic о подсчёте токеновfirebase.google.com/docs/ai-logic/count-tokens
  11. 11.#29530github.com/google-gemini/gemini-cli/issues/29530
  12. 12.#29574github.com/google-gemini/gemini-cli/issues/29574
  13. 13.#45359github.com/anomalyco/opencode/issues/45359
  14. 14.#55694github.com/anomalyco/opencode/issues/55694
  15. 15.#1052github.com/Zoo-Code-Org/Zoo-Code/issues/1052
  16. 16.#38537github.com/BerriAI/litellm/issues/38537
  17. 17.#2631github.com/567-labs/instructor/issues/2631
  18. 18.руководство EvoLink по настройке Gemini в SillyTavernevolink.ai/blog/sillytavern-gemini-setup-troubleshooting