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

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

- URL: https://blog.laozhang.ai/ru/posts/gemini-requests-ending-with-model-turn-not-supported
- Published: 2026-10-29
- Updated: 2026-10-29
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ru/about)
- Topic: Устранение ошибок
- Tags: Gemini API, Gemini 4 Argon, Ошибка 400, Requests ending with a model turn, prefill, countTokens, Gemini CLI, Vertex AI

---
Ошибка `400 INVALID_ARGUMENT: Requests ending with a model turn are not supported.` означает, что Google получил запрос, в котором последний непустой ход в массиве `contents` имеет role `model`, то есть принадлежит модели (в формате OpenAI это сообщение `assistant`). Правило Google объявил [в описании изменений Gemini 3.6 Flash](https://ai.google.dev/gemini-api/docs/whats-new-gemini-3.6): оно действует для 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](https://ai.google.dev/gemini-api/docs/generate-content/latest-model) это правило отдельно не повторяется, но формулировка «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)](https://github.com/code-yeongyu/senpi/issues/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](https://github.com/langchain-ai/langchain-google/issues/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 — наш собственный сервис](https://blog.laozhang.ai/ru/about#laozhang); его цены — наши тарифы, а не независимое сравнение.*

| Содержимое `contents` (последний элемент справа) | Результат |
| --- | --- |
| `[user]` | 200 |
| `[user, model "Rain"]`, prefill | 400, при повторе в 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](https://blog.laozhang.ai/posts/ru/gemini-requests-ending-with-model-turn-not-supported/img/model-turn-test-pairs.webp)

Выборка небольшая: один эндпоинт, один день, по одному запуску на форму (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](https://ai.google.dev/gemini-api/docs/generate-content/structured-output). Тогда модель вернёт JSON без заготовки. Если же prefill служил для продолжения обрезанного длинного ответа, причину обрыва нужно искать в `finishReason`. Об этом подробно в статье [Gemini 4 Argon API: доступ, finish_reason и обрыв ответа](https://blog.laozhang.ai/ru/posts/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](https://blog.laozhang.ai/posts/ru/gemini-requests-ending-with-model-turn-not-supported/img/function-response-part-order.webp)

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

Автоматический повтор здесь не нужен. В [руководстве Google по устранению неполадок Gemini API](https://ai.google.dev/gemini-api/docs/troubleshooting) повторять советуют только временные ошибки 429, 408 и 5xx, а 400 — это ошибка в самом запросе, и тот же запрос снова получит 400. Мейнтейнер senpi 20 октября 2026 года тоже попросил считать этот 400 ошибкой запроса, а не поводом для паузы или переключения на запасную модель. Если в вашем коде 400 запускает цикл повторов, как в [livekit agents-js #2108](https://github.com/livekit/agents-js/issues/2108), агент просто замолкает.

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

Об этом сообщил мейнтейнер плагина Obsidian Gemini Scribe allenhutchison в [obsidian-gemini #1708](https://github.com/allenhutchison/obsidian-gemini/issues/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 о подсчёте токенов](https://firebase.google.com/docs/ai-logic/count-tokens?hl=en) `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](https://github.com/google-gemini/gemini-cli/issues/29530), [#29574](https://github.com/google-gemini/gemini-cli/issues/29574)) | Исправления влиты 7 и 13 октября, оба есть в стабильной v0.65.0 от 20 октября | Обновиться до v0.65.0 или новее |
| opencode | Служебное сообщение о лимите шагов добавляется как ответ ассистента ([#45359](https://github.com/anomalyco/opencode/issues/45359)); чтение `.png` через OpenRouter ([#55694](https://github.com/anomalyco/opencode/issues/55694)) | #45359 закрыт, но 15 сентября ошибка повторялась на 1.18.31, слияние PR #55382 не подтверждено; #55694 открыт | Отправить новое сообщение, после него сессия продолжается |
| Zoo Code, Kilo Code | Zoo Code на Vertex дописывает prefill для вызова инструментов ([#1052](https://github.com/Zoo-Code-Org/Zoo-Code/issues/1052)); в Kilo Code шаги сохранялись не по порядку | Открыто | Автор отчёта по Zoo Code временно вернулся на `gemini-3.5-flash` |
| SillyTavern и другие ролевые фронтенды | Prefill ассистента, «продолжить», настройки начала ответа, преобразование истории, расширения | Зависит от пресета | Новый чат, последним — настоящее сообщение пользователя; отключить prefill и продолжение, затем включать по одному |
| LangChain (langchain-google, vertexai) | Результат инструмента и следующий `HumanMessage` слиты в один ход `user` ([#1995](https://github.com/langchain-ai/langchain-google/issues/1995)) | Открыто | Не ставить сообщение пользователя сразу за результатом инструмента или разделять их вручную |
| LiteLLM | История на Vertex кончается текстовым ответом ассистента ([#38537](https://github.com/BerriAI/litellm/issues/38537)) | Открыто | Перед вызовом убирать хвостовой ответ ассистента или добавлять сообщение пользователя |
| OpenRouter | Результат инструмента с изображением стоит последним; текст Google виден только в `metadata.raw` | Открыто в hermes-agent #139313 | Результат текстом, изображение отдельным сообщением пользователя |
| instructor | Повторный запрос структурированного вывода (reask) заканчивается ходом модели ([#2631](https://github.com/567-labs/instructor/issues/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](https://blog.laozhang.ai/ru/posts/gemini-cli-install).

В SillyTavern названия пунктов зависят от версии и пресета, поэтому проще проверить сам эффект: начать новый чат, где последним идёт ваше сообщение, и по очереди возвращать prefill ассистента, продолжение ответа и обработку истории, пока ошибка не вернётся. Так советует [руководство EvoLink по настройке Gemini в SillyTavern](https://evolink.ai/blog/sillytavern-gemini-setup-troubleshooting) от 16 октября 2026 года.

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

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

Нет. Там API не принимает саму роль сообщения, а здесь роль допустима, но стоит не на своём месте. Про неподдерживаемые роли написано в статье [Как исправить API 400 с неподдерживаемой ролью и не сломать системные инструкции](https://blog.laozhang.ai/ru/posts/api-400-role-system-is-not-supported-on-this-model).

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

У Claude похожий запрет на prefill, но у него свой текст ошибки (`This model does not support assistant message prefill`) и свой список моделей. Подробности в статье [Ошибка 400 prefill в Claude: на каких моделях и чем заменить](https://blog.laozhang.ai/ru/posts/claude-opus-prefill-error-fix).

### Что значит «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` они не связаны.

## Источники

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

- [в описании изменений Gemini 3.6 Flash](https://ai.google.dev/gemini-api/docs/whats-new-gemini-3.6) (ai.google.dev)
- [Gemini 4 Argon](https://ai.google.dev/gemini-api/docs/generate-content/latest-model) (ai.google.dev)
- [трекере агента senpi (issue #3633)](https://github.com/code-yeongyu/senpi/issues/3633) (github.com)
- [langchain-google #1995](https://github.com/langchain-ai/langchain-google/issues/1995) (github.com)
- [руководстве Google по структурированному выводу в generateContent](https://ai.google.dev/gemini-api/docs/generate-content/structured-output) (ai.google.dev)
- [hermes-agent #139313](https://github.com/NousResearch/hermes-agent/issues/139313) (github.com)
- [руководстве Google по устранению неполадок Gemini API](https://ai.google.dev/gemini-api/docs/troubleshooting) (ai.google.dev)
- [livekit agents-js #2108](https://github.com/livekit/agents-js/issues/2108) (github.com)
- [obsidian-gemini #1708](https://github.com/allenhutchison/obsidian-gemini/issues/1708) (github.com)
- [документации Firebase AI Logic о подсчёте токенов](https://firebase.google.com/docs/ai-logic/count-tokens?hl=en) (firebase.google.com)
- [#29530](https://github.com/google-gemini/gemini-cli/issues/29530) (github.com)
- [#29574](https://github.com/google-gemini/gemini-cli/issues/29574) (github.com)
- [#45359](https://github.com/anomalyco/opencode/issues/45359) (github.com)
- [#55694](https://github.com/anomalyco/opencode/issues/55694) (github.com)
- [#1052](https://github.com/Zoo-Code-Org/Zoo-Code/issues/1052) (github.com)
- [#38537](https://github.com/BerriAI/litellm/issues/38537) (github.com)
- [#2631](https://github.com/567-labs/instructor/issues/2631) (github.com)
- [руководство EvoLink по настройке Gemini в SillyTavern](https://evolink.ai/blog/sillytavern-gemini-setup-troubleshooting) (evolink.ai)
