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

Ошибка Thought Signature в Nano Banana 2: 400 на втором ходе

Второй ход в Nano Banana 2 падает с 400, если прошлую картинку отправили без подписи мышления (thought signature). Помогают previous_interaction_id и чат SDK.

LaoZhang AI TeamОпубликованоОбновлено 8 мин чтения
Содержание
Nano Banana 2: сохранение полного ответа между ходами предотвращает потерю thought signature

Ошибка вида Image part is missing a thought_signature in content position 2, part position 1 означает одно: в запросе на второй ход лежит изображение, которое раньше сгенерировала сама модель, но без подписи мышления (thought signature), пришедшей вместе с ним. Nano Banana 2 (gemini-3.1-flash-image) такой запрос отклоняет с HTTP 400 INVALID_ARGUMENT. Чинится это не подстановкой какой-то строки, а тем, чтобы ответ модели попадал в следующий запрос без изменений. Проще всего вести диалог через Interactions API с previous_interaction_id: тогда подписи хранит сервер. В generateContent используйте чат SDK или добавляйте в историю объект ответа целиком. Если историю собирает фреймворк, обновите его или откройте issue с точным текстом ошибки.

Что значит «Image part is missing a thought_signature»

Подпись мышления — это зашифрованное представление внутренних рассуждений модели. По руководству Google о мышлении она нужна, чтобы модель продолжала ход рассуждений между ходами диалога. Расшифровать или собрать её вручную нельзя, её можно только вернуть такой, какой она пришла. Отдельная страница /thought-signatures, на которую ссылаются старые сообщения об ошибке, теперь перенаправляет в это руководство.

В generateContent у подписи нет своего блока: это метаданные, прикреплённые к одной из частей ответа (parts), например к части с картинкой (inlineData), к последней текстовой части или к вызову функции. Когда приложение пересобирает историю «по смыслу» (взяло текст, взяло байты изображения, положило в новую часть с ролью model), метаданные теряются. На первом ходе всё работает, потому что модели ещё нечего проверять. Второй ход отправляет её же картинку без подписи и получает 400.

Позиции в тексте ошибки подсказывают, где искать: content position указывает на элемент массива contents, part position — на часть внутри него. С какого числа начинается счёт, Google не поясняет, поэтому надёжнее найти в истории ход модели с изображением и проверить, есть ли у его частей поле thoughtSignature.

Та же причина выглядит по-разному в зависимости от интерфейса:

ГдеКак выглядит
generateContent, HTTP-ответ400 INVALID_ARGUMENT, текст про отсутствующую thought_signature
generateContent, поле finishReasonMISSING_THOUGHT_SIGNATURE («в запросе не хватает хотя бы одной подписи мышления»)
Interactions APIкод ошибки missing_thought_signature

Значения из второй и третьей строк перечислены в справочнике generateContent и на странице ошибок API. Если в ответе вообще нет картинки и при этом нет ошибки, причина другая — разбор по полям ответа есть в статье «Nano Banana не генерирует изображение в API: как найти причину».

Почему ошибка появилась на Nano Banana 2, а на Nano Banana Pro её не было

Код, который работал с Nano Banana Pro, может сломаться на Nano Banana 2, хотя обе модели относятся к Gemini 3. Страница Google Cloud Thought signatures прямо говорит, что Gemini 3 Pro Image (gemini-3-pro-image) не проверяет подписи и не возвращает 400, если их не вернули. Возвращать их всё равно нужно, иначе модель теряет контекст между правками.

Про Nano Banana 2 в той же документации отдельного правила нет. Зато есть сообщение разработчиков: в issue #12988 в репозитории Vercel AI SDK, открытом 2 марта 2026 года, второй ход после генерации картинки в gemini-3.1-flash-image-preview упал с 400 INVALID_ARGUMENT и тем самым текстом про content position 2, part position 1. SDK отправлял прошлое изображение без подписи. Тот же сценарий, по словам автора, работал с gemini-2.5-flash-image. Судя по этому отчёту, Nano Banana 2 подписи частей с изображением проверяет, а Pro, по документации, при пропуске подписи ошибку не возвращает. Полагаться на это исключение не стоит: в отчёте о плагине Dify за декабрь 2025 года та же 400 с «Image part is missing a thought_signature» пришла от предварительной версии Nano Banana Pro.

Оба названия из того отчёта уже недоступны. Предварительная версия gemini-3.1-flash-image-preview отключена 25 июня 2026 года, gemini-2.5-flash-image — 2 октября 2026 года (по странице выводимых из эксплуатации моделей). Текущие ID: gemini-3.1-flash-image для Nano Banana 2 и gemini-3-pro-image для Nano Banana Pro. Если вы переносите код со старых ID, проверяйте именно второй и последующие ходы, а не только первую генерацию.

Способ 1: Interactions API и previous_interaction_id

Гайд Google по генерации изображений сейчас построен на Interactions API, и многоходовое редактирование там делается через previous_interaction_id. В режиме с состоянием (хранение включено, следующий запрос ссылается на прошлый) сервер сам держит историю вместе с блоками мышления и подписями. По руководству о мышлении, в этом режиме «ничего делать с подписями не нужно». Для новой интеграции это самый короткий путь: ошибке просто неоткуда взяться.

python
# Пример не запускался; формы вызовов взяты из гайда Google по изображениям.
import base64
from google import genai

client = genai.Client()  # ключ из переменной окружения GEMINI_API_KEY

first = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Керамическая кружка на деревянном столе, мягкий утренний свет",
)
with open("mug_v1.png", "wb") as f:
    f.write(base64.b64decode(first.output_image.data))

# Второй ход: передаём только id прошлого шага, историю и подписи хранит сервер
second = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Сделай кружку тёмно-синей, остальное не меняй",
    previous_interaction_id=first.id,
)
with open("mug_v2.png", "wb") as f:
    f.write(base64.b64decode(second.output_image.data))

Если хранение (store) выключено и всю историю вы присылаете сами, это уже режим без состояния. Тогда правило из руководства строгое: блоки мышления нужно отправлять обратно ровно в том виде, в каком они пришли, ничего не удаляя и не меняя. Это касается и шагов встроенных инструментов вроде google_search: у них свои подписи, и их тоже нужно возвращать. Пример многоходового редактирования в гайде Google как раз использует поиск, так что этот случай легко пропустить.

Способ 2: generateContent — чат SDK или ответ модели целиком

Если проект уже работает через generateContent, переписывать его на Interactions API не обязательно. В официальном SDK google-genai (from google import genai) подписи обрабатываются автоматически, когда вы пользуетесь чатом или добавляете в историю объект ответа модели без изменений. Это сказано на той же странице Google Cloud, и её пример многоходового редактирования изображений сделан через чат.

python
# Пример не запускался; чат SDK сам возвращает подписи в следующий запрос.
from google import genai
from google.genai import types

client = genai.Client()
chat = client.chats.create(
    model="gemini-3.1-flash-image",
    config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
)

def save_images(response, name):
    for i, part in enumerate(response.candidates[0].content.parts):
        if part.inline_data:
            with open(f"{name}_{i}.png", "wb") as f:
                f.write(part.inline_data.data)

r1 = chat.send_message("Керамическая кружка на деревянном столе")
save_images(r1, "mug_v1")

r2 = chat.send_message("Сделай кружку тёмно-синей, остальное не меняй")
save_images(r2, "mug_v2")

Обратите внимание: старый пакет google-generativeai с genai.GenerativeModel и start_chat() в текущей документации Google не используется. Если ваш код начинается с import google.generativeai, переход на google-genai стоит сделать заодно.

Если историю хранит ваш код

Когда чат SDK не подходит (история лежит в базе, запросы идут с разных серверов), правило одно: ход модели кладётся в историю как есть, объектом Content из ответа, а не пересобирается из текста и байтов.

python
# Правильно: ответ модели целиком, вместе с подписью на части с картинкой
history = [
    types.Content(role="user", parts=[types.Part(text=prompt_1)]),
    r1.candidates[0].content,
    types.Content(role="user", parts=[types.Part(text=prompt_2)]),
]
r2 = client.models.generate_content(
    model="gemini-3.1-flash-image",
    contents=history,
    config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
)

# Так и получается 400: картинка модели пересобрана в новую часть без подписи
broken_turn = types.Content(
    role="model",
    parts=[types.Part.from_bytes(data=image_bytes, mime_type="image/png")],
)

Если историю нужно сохранить между сессиями, сохраняйте все части хода модели со всеми полями, включая thoughtSignature (в REST-ответе поле называется так, в Python SDK — thought_signature). Google Cloud перечисляет ещё три правила для ручной работы: возвращать подпись внутри той же части, в которой она пришла; не склеивать часть с подписью и часть без неё; не объединять две части с подписями, потому что строки подписей не складываются.

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

Потоковый ответ: подпись в части с пустым текстом

При потоковой генерации подпись может прийти в отдельной части с пустым текстом. Google Cloud советует разбирать все части до появления finish_reason. Цикл, который берёт только chunk.text или пропускает части с пустой строкой, подпись выбросит, и следующий ход упадёт. Если вы склеиваете поток в итоговый ответ сами, собирайте именно части (parts) со всеми полями, а не только текст.

Потоковый ответ: сохранить все parts, включая пустой текст и метаданные подписи

Способ 3: фреймворк теряет подпись — Vercel AI SDK, n8n, Dify, LangGraph

Если вы не собираете запросы сами, а работаете через обёртку, ошибка почти всегда значит одно: библиотека хранит историю как «текст плюс вложения» и при следующем вызове пересобирает части без метаданных.

  • Vercel AI SDK. Тот самый случай из issue #12988 исправлен изменением «fix missing support for image thought signatures», которое вошло в пакет ai версии 6.0.114. Если ошибка появилась на второй правке картинки, сначала обновите ai до 6.0.114 или новее.
  • n8n и плагин Gemini для Dify. Похожие сообщения пользователей есть для обеих платформ. Какая версия узла или плагина это исправляет, смотрите в журнале изменений. Пока исправления нет, рабочий путь — HTTP-запрос к API напрямую, где ответ модели сохраняется целиком, либо Interactions API с previous_interaction_id.
  • LangGraph, LangChain и другие обёртки. Проверьте, сохраняет ли конвертер сообщений метаданные отдельных частей ответа. Если в сохранённой истории у хода модели с картинкой нет thought_signature, проблема именно там.

Если обновление не помогло, откройте issue в репозитории фреймворка. Приложите точный текст ошибки с позициями, ID модели (gemini-3.1-flash-image) и фрагмент истории второго запроса без данных изображения. По этим трём вещам разработчики библиотеки быстро видят, на каком шаге пропадает подпись.

Подписи при вызове функций в Gemini 3: что проверяется и когда возвращается 400

Если в том же диалоге модель вызывает функции (агентный сценарий, где картинка — один из шагов), правила строже, и они уже официально задокументированы. По странице Google Cloud, модели Gemini 3 возвращают 400, если не вернуть обязательную подпись, причём даже при минимальном уровне мышления.

Подписи в вызовах функций Gemini 3: возвращать подписанные части и порядок параллельных вызовов

  • Последовательные вызовы. Ход начинается с последнего сообщения пользователя, которое не является ответом функции (functionResponse). Внутри хода каждый шаг с вызовом функции несёт подпись на первой части functionCall. Проверяются все шаги текущего хода, и пропуск любой из этих подписей даёт 400.
  • Параллельные вызовы. Подпись есть только у первой части functionCall. Возвращать нужно сначала все вызовы, потом все ответы: FC1+подпись, FC2, FR1, FR2. Чередование FC1, FR1, FC2, FR2 тоже даёт 400.
  • Части без вызова функций. Подпись может прийти в последней части ответа. Вернуть её рекомендуется, но без неё ошибки не будет. Исключение, по сообщениям разработчиков, — части с изображением в Nano Banana 2 (см. выше).

skip_thought_signature_validator — это значение, которое Google разрешает записать в thought_signature для частей functionCall, сгенерированных не этим API, например при переносе истории от модели, которая подписей не выдаёт. Google называет его крайней мерой: оно ухудшает работу модели. Для частей с изображением такой вариант не описан, и рассчитывать на него при редактировании картинок не стоит.

В примерах Google Cloud для Chat Completions (OpenAI-совместимого интерфейса Vertex) подпись лежит в каждом элементе tool_calls по пути extra_content.google.thought_signature. Логика та же: элемент нужно вернуть в следующем запросе без изменений.

Подпись мышления (thought signature): короткие ответы

Можно ли подставить фиктивную подпись к картинке, чтобы убрать 400?

Задокументированного способа нет. skip_thought_signature_validator описан только для частей functionCall, которые API не генерировал, и даже там это крайняя мера. Для изображений рабочие варианты — вернуть настоящую подпись или начать новый диалог с картинкой во входном сообщении пользователя.

Нужно ли возвращать подписи, если уровень мышления минимальный?

Да. Google Cloud пишет, что для моделей Gemini 3 подписи из прошлых ответов нужно возвращать и при минимальном уровне мышления, иначе на обязательных местах будет 400.

Что значит «Thought signature is not valid»?

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

Можно ли сменить модель посреди диалога?

В Interactions API без состояния руководство Google велит при смене модели всё равно отправлять блоки мышления предыдущей модели, а совместимостью занимается сервер. Страница Google Cloud добавляет общее правило: историю передавайте либо полностью (мысли, вызовы функций, ответы), либо без этого контекста целиком. Частичная история ухудшает ответы.

Где разобраны другие ошибки генерации изображений Gemini?

Ограничения по частоте, пустые ответы и сломанные параметры собраны в разборе ошибок генерации изображений Gemini. Сбои в приложении Gemini, а не в API, описаны в статье «Nano Banana не работает в Gemini», а сообщение «Something went wrong (5)» — в статье «Nano Banana Pro: ошибка 5 в Gemini». Базовая настройка ключа, моделей и кода на Python — в руководстве Gemini Image API.

Официальная документация

Параметры запросов, цены и правила списания средств описаны в документации LaoZhang API для разработчиков: биллинг и ошибки генерации изображений.

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

Источники8

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

  1. 1.руководству Google о мышленииai.google.dev/gemini-api/docs/thinking
  2. 2.справочнике generateContentai.google.dev/api/generate-content
  3. 3.ошибок APIai.google.dev/gemini-api/docs/api-errors
  4. 4.Thought signaturesdocs.cloud.google.com/gemini-enterprise-agent-platform/models/thinking/thought-signatures
  5. 5.issue #12988 в репозитории Vercel AI SDKgithub.com/vercel/ai/issues/12988
  6. 6.отчёте о плагине Dify за декабрь 2025 годаgithub.com/langgenius/dify-official-plugins/issues/2262
  7. 7.странице выводимых из эксплуатации моделейai.google.dev/gemini-api/docs/deprecations
  8. 8.Гайд Google по генерации изображенийai.google.dev/gemini-api/docs/image-generation
Полное руководство по устранению ошибок Gemini API 2026
Руководства по API

Устранение ошибок Gemini API: полное руководство по исправлению 429, 400, 500 (2026)

Подробный разбор каждой ошибки Gemini API с рабочими решениями. Охватывает 429 RESOURCE_EXHAUSTED, 400 INVALID_ARGUMENT, 500 INTERNAL, 503 UNAVAILABLE и 504 DEADLINE_EXCEEDED с готовым кодом повторных запросов на Python и JavaScript. Включает проверенные лимиты после сокращения бесплатного уровня в декабре 2025.

25 мин
Иллюстрация сравнения Nano Banana Pro и Midjourney v8
Генерация изображений

Nano Banana Pro или Midjourney v8: что выбрать для генерации и правок

Nano Banana Pro удобен, когда нужны последовательные правки и официальный API. Midjourney V8.2 предлагает ручную работу с визуальным стилем и тоже умеет редактировать по инструкции. Выбор зависит от нужного результата, способа управления и числа доработок.

12 мин
Nano Banana 2: бесплатное создание изображений в приложениях и отдельный платный доступ через API
Генерация изображений

Nano Banana 2 бесплатно: как попробовать и что изменилось в Gemini

Попробовать создание изображений без подписки можно в Gemini. Но с 9 октября бесплатные аккаунты переходят на Auto, поэтому результат нельзя автоматически считать работой Nano Banana 2. Ниже — первый запрос, правка, скачивание и выбор после исчерпания лимита.

8 мин