bug: When calling Google models in a multi-turn conversation, an error occurs because thought_signature is not included. #948

Open
opened 2026-02-16 10:21:05 -05:00 by yindo · 6 comments
Owner

Originally created by @BeautyyuYanli on GitHub (Jan 26, 2026).

Originally assigned to: @BeautyyuYanli on GitHub.

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.11.4

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

This issue can only be reproduced with Nano Banana Pro. It cannot be reproduced with Nano Banana.

Gemini 3 Pro Preview does not have this problem (but Gemini 3 Pro Preview does not support file output). It is recommended to test gemini-2.5-flash-image / gemini-3-pro-image-preview.

Steps to reproduce
Send an image to Nano Banana Pro and have it process the image.
In the same conversation, reply using Nano Banana and ask it to modify the image.

Image

✔️ Expected Behavior

Multi-turn conversations should be processed correctly.

Actual Behavior

Run failed: req_id: 861eb74ff9 PluginInvokeError: {"args":{},"error_type":"ClientError","message":"400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Image part is missing a thought_signature in content position 2, part position 1. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures#model-behavior for more details.', 'status': 'INVALID_ARGUMENT'}}"}
Originally created by @BeautyyuYanli on GitHub (Jan 26, 2026). Originally assigned to: @BeautyyuYanli on GitHub. ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.11.4 ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce This issue can only be reproduced with Nano Banana Pro. It cannot be reproduced with Nano Banana. Gemini 3 Pro Preview does not have this problem (but Gemini 3 Pro Preview does not support file output). It is recommended to test gemini-2.5-flash-image / gemini-3-pro-image-preview. Steps to reproduce Send an image to Nano Banana Pro and have it process the image. In the same conversation, reply using Nano Banana and ask it to modify the image. <img width="1014" height="578" alt="Image" src="https://github.com/user-attachments/assets/e5f404ac-4a3e-4186-b4f2-377f62c5d062" /> ### ✔️ Expected Behavior Multi-turn conversations should be processed correctly. ### ❌ Actual Behavior ``` Run failed: req_id: 861eb74ff9 PluginInvokeError: {"args":{},"error_type":"ClientError","message":"400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Image part is missing a thought_signature in content position 2, part position 1. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures#model-behavior for more details.', 'status': 'INVALID_ARGUMENT'}}"} ```
yindo added the bug label 2026-02-16 10:21:05 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jan 26, 2026):

This error happens because the Gemini plugin does not capture and replay the actual thought_signature from the Gemini API response in multi-turn conversations. Instead, it uses a static placeholder, which only works for the first image generation. For subsequent turns, the Gemini API requires the exact thought_signature from the previous response; otherwise, it returns a 400 INVALID_ARGUMENT error as described in the Gemini API docs and confirmed in related issues.

To resolve this, update the Gemini plugin to version 0.7.0 or later, which correctly handles thought_signature passthrough for multi-turn conversations (details). If updating is not possible, the only reliable workaround is to start a new conversation for each image generation or use a model that does not require thought_signature (like qwen-max or DeepSeek) for multi-turn tasks.

A permanent fix requires code changes so the plugin and core message model capture, persist, and replay the actual thought_signature from each Gemini response and include it in subsequent requests (reference).

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 26, 2026): <!-- Answer --> This error happens because the Gemini plugin does not capture and replay the actual `thought_signature` from the Gemini API response in multi-turn conversations. Instead, it uses a static placeholder, which only works for the first image generation. For subsequent turns, the Gemini API requires the exact `thought_signature` from the previous response; otherwise, it returns a 400 INVALID_ARGUMENT error as described in the [Gemini API docs](https://ai.google.dev/gemini-api/docs/thought-signatures) and confirmed in [related issues](https://github.com/langgenius/dify/issues/29152). To resolve this, update the Gemini plugin to version 0.7.0 or later, which correctly handles `thought_signature` passthrough for multi-turn conversations ([details](https://github.com/langgenius/dify/issues/29187)). If updating is not possible, the only reliable workaround is to start a new conversation for each image generation or use a model that does not require `thought_signature` (like qwen-max or DeepSeek) for multi-turn tasks. A permanent fix requires code changes so the plugin and core message model capture, persist, and replay the actual `thought_signature` from each Gemini response and include it in subsequent requests ([reference](https://github.com/langgenius/dify/issues/29152)). <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/e33a6fd8-05ef-4d6e-9f54-4ef85eb31744?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20error%20happens%20because%20the%20Gemini%20plugin%20does%20not%20capture%20and%20replay%20the%20actual%20%60thought_signature%60%20from%20the%20Gemini%20API%20response%20in%20multi-turn%20conversations.%20Instead%2C%20it%20uses%20a%20static%20placeholder%2C%20which%20only%20works%20for%20the%20first%20image%20generation.%20For%20subsequent%20turns%2C%20the%20Gemini%20API%20requires%20the%20exact%20%60thought_signature%60%20from%20the%20previous%20response%3B%20otherwise%2C%20it%20returns%20a%20400%20INVALID_ARGUMENT%20error%20as%20described%20in%20the%20%5BGemini%20API%20docs%5D%28https%3A//ai.google.dev/gemini-api/docs/thought-signatures%29%20and%20confirmed%20in%20%5Brelated%20issues%5D%28https%3A//github.com/langgenius/dify/issues/29152%29.%0A%0ATo%20resolve%20this%2C%20update%20the%20Gemini%20plugin%20to%20version%200.7.0%20or%20later%2C%20which%20correctly%20handles%20%60thought_signature%60%20passthrough%20for%20multi-turn%20conversations%20%28%5Bdetails%5D%28https%3A//github.com/langgenius/dify/issues/29187%29%29.%20If%20updating%20is%20not%20possible%2C%20the%20only%20reliable%20workaround%20is%20to%20start%20a%20new%20conversation%20for%20each%20image%20generation%20or%20use%20a%20model%20that%20does%20not%20require%20%60thought_signature%60%20%28like%20qwen-max%20or%20DeepSeek%29%20for%20multi-turn%20tasks.%0A%0AA%20permanent%20fix%20requires%20code%20changes%20so%20the%20plugin%20and%20core%20message%20model%20capture%2C%20persist%2C%20and%20replay%20the%20actual%20%60thought_signature%60%20from%20each%20Gemini%20response%20and%20include%20it%20in%20subsequent%20requests%20%28%5Breference%5D%28https%3A//github.com/langgenius/dify/issues/29152%29%29.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/31557)
Author
Owner

@BeautyyuYanli commented on GitHub (Jan 26, 2026):

Proposal: Preserve thought_signature (and similar provider-specific fields) via opaque_body

1) What is thought_signature?

Through testing, we confirm that thought_signature is a signature attached to a specific content part of a model response (e.g., an image content part).
It is required for certain kinds of content parts, and is not a field for the whole response message or the whole conversation thread.

2) Solution overview: introduce opaque_body for pass-through

To solve the problem (and to future-proof against similar provider-specific requirements), introduce an opaque_body field:

  • Content-part level: content_part.opaque_body
    Stores provider-specific opaque metadata for that content part (e.g., thought_signature for an image part).
  • Message level: message.opaque_body
    Reserves space for provider-specific opaque metadata attached to the message as a whole (if any provider needs it later).
  • Behavior contract: opaque_body must be passed through without modification across:
    • Dify api
    • dify-plugin-daemon
    • LLM provider plugins (e.g., Gemini-related plugins)
      This ensures that when the next turn references prior multimodal outputs, all required provider metadata is still available and can be sent back to the provider API.

3) Data persistence & chat history handling in Dify (key focus: Workflow LLM Node)

Dify has multiple code paths that build / transform / store chat history. To make opaque_body truly work, Dify must persist and replay it when reconstructing conversation context.

Key requirement: Workflow LLM Node must store opaque_body (both message-level and content-part-level) into whatever history / state it uses, and include it when assembling the subsequent request payload.

Additionally, any other chat-history handling components should do the same too.

@BeautyyuYanli commented on GitHub (Jan 26, 2026): # Proposal: Preserve thought_signature (and similar provider-specific fields) via opaque_body ## 1) What is thought_signature? Through testing, we confirm that thought_signature is a signature attached to a specific content part of a model response (e.g., an image content part). It is required for certain kinds of content parts, and is not a field for the whole response message or the whole conversation thread. ## 2) Solution overview: introduce opaque_body for pass-through To solve the problem (and to future-proof against similar provider-specific requirements), introduce an opaque_body field: - Content-part level: content_part.opaque_body Stores provider-specific opaque metadata for that content part (e.g., thought_signature for an image part). - Message level: message.opaque_body Reserves space for provider-specific opaque metadata attached to the message as a whole (if any provider needs it later). - Behavior contract: opaque_body must be passed through without modification across: - Dify api - dify-plugin-daemon - LLM provider plugins (e.g., Gemini-related plugins) This ensures that when the next turn references prior multimodal outputs, all required provider metadata is still available and can be sent back to the provider API. ## 3) Data persistence & chat history handling in Dify (key focus: Workflow LLM Node) Dify has multiple code paths that build / transform / store chat history. To make opaque_body truly work, Dify must persist and replay it when reconstructing conversation context. Key requirement: Workflow LLM Node must store opaque_body (both message-level and content-part-level) into whatever history / state it uses, and include it when assembling the subsequent request payload. Additionally, any other chat-history handling components should do the same too.
Author
Owner

@BeautyyuYanli commented on GitHub (Jan 26, 2026):

A previous fix for Vertex is a temporary workaround because the plugin instance is desgin to be stateless https://github.com/langgenius/dify-official-plugins/pull/2387

@BeautyyuYanli commented on GitHub (Jan 26, 2026): A previous fix for Vertex is a temporary workaround because the plugin instance is desgin to be stateless https://github.com/langgenius/dify-official-plugins/pull/2387
Author
Owner
@BeautyyuYanli commented on GitHub (Jan 26, 2026): - [x] Previous changes of code langgenius/dify#31499 langgenius/dify#31564 - [ ] Support opaque_body for the components https://github.com/langgenius/dify-plugin-sdks/pull/284 langgenius/dify#31566 https://github.com/langgenius/dify-plugin-daemon/pull/585 - [ ] Preserving opaque_body for chat history
Author
Owner

@dosubot[bot] commented on GitHub (Jan 26, 2026):

This error happens because Google Gemini models (like Nano Banana Pro) require a thought_signature token in the image part of the request payload for multi-turn conversations. The plugin is supposed to capture the thought_signature from the previous Gemini API response and replay it in subsequent requests to maintain context. Right now, the Dify Gemini plugin does not do this—it uses a hard-coded placeholder that only works for the first turn, so the second image request fails with a 400 INVALID_ARGUMENT error from the Gemini API [source].

The main Dify codebase does not build the Gemini API payload; this logic is in the plugin server, and the parameter is not set anywhere in the main repo [source]. There is no official fix or merged pull request for this issue yet—maintainers have mentioned possible bypasses, but nothing is documented or released [source].

To resolve this, the plugin needs to capture and replay the real thought_signature from Gemini API responses as described in the Gemini API documentation. For now, the only workaround is to use a different model (like qwen-max), but this does not support Gemini-specific features [source]. If you need Gemini features, you’ll need to monitor plugin updates or consider contributing a patch that implements proper thought_signature handling.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 26, 2026): <!-- Answer --> This error happens because Google Gemini models (like Nano Banana Pro) require a `thought_signature` token in the image part of the request payload for multi-turn conversations. The plugin is supposed to capture the `thought_signature` from the previous Gemini API response and replay it in subsequent requests to maintain context. Right now, the Dify Gemini plugin does not do this—it uses a hard-coded placeholder that only works for the first turn, so the second image request fails with a 400 INVALID_ARGUMENT error from the Gemini API [[source](https://github.com/langgenius/dify-official-plugins/issues/2262)]. The main Dify codebase does not build the Gemini API payload; this logic is in the plugin server, and the parameter is not set anywhere in the main repo [[source](https://github.com/langgenius/dify/blob/8519b16cfc68291e0c74e74067723e477eecdad1/api/core/model_runtime/model_providers/model_provider_factory.py#L26-L352)]. There is no official fix or merged pull request for this issue yet—maintainers have mentioned possible bypasses, but nothing is documented or released [[source](https://github.com/langgenius/dify-official-plugins/issues/2168)]. To resolve this, the plugin needs to capture and replay the real `thought_signature` from Gemini API responses as described in the [Gemini API documentation](https://ai.google.dev/gemini-api/docs/thought-signatures#model-behavior). For now, the only workaround is to use a different model (like qwen-max), but this does not support Gemini-specific features [[source](https://github.com/langgenius/dify-official-plugins/issues/2168)]. If you need Gemini features, you’ll need to monitor plugin updates or consider contributing a patch that implements proper `thought_signature` handling. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/ba819b00-64fc-4942-b43c-d9dd4d6ec4a9?feedback_type=other)</sup> [![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20error%20happens%20because%20Google%20Gemini%20models%20%28like%20Nano%20Banana%20Pro%29%20require%20a%20%60thought_signature%60%20token%20in%20the%20image%20part%20of%20the%20request%20payload%20for%20multi-turn%20conversations.%20The%20plugin%20is%20supposed%20to%20capture%20the%20%60thought_signature%60%20from%20the%20previous%20Gemini%20API%20response%20and%20replay%20it%20in%20subsequent%20requests%20to%20maintain%20context.%20Right%20now%2C%20the%20Dify%20Gemini%20plugin%20does%20not%20do%20this%E2%80%94it%20uses%20a%20hard-coded%20placeholder%20that%20only%20works%20for%20the%20first%20turn%2C%20so%20the%20second%20image%20request%20fails%20with%20a%20400%20INVALID_ARGUMENT%20error%20from%20the%20Gemini%20API%20%5B%5Bsource%5D%28https%3A//github.com/langgenius/dify-official-plugins/issues/2262%29%5D.%0A%0AThe%20main%20Dify%20codebase%20does%20not%20build%20the%20Gemini%20API%20payload%3B%20this%20logic%20is%20in%20the%20plugin%20server%2C%20and%20the%20parameter%20is%20not%20set%20anywhere%20in%20the%20main%20repo%20%5B%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/8519b16cfc68291e0c74e74067723e477eecdad1/api/core/model_runtime/model_providers/model_provider_factory.py%23L26-L352%29%5D.%20There%20is%20no%20official%20fix%20or%20merged%20pull%20request%20for%20this%20issue%20yet%E2%80%94maintainers%20have%20mentioned%20possible%20bypasses%2C%20but%20nothing%20is%20documented%20or%20released%20%5B%5Bsource%5D%28https%3A//github.com/langgenius/dify-official-plugins/issues/2168%29%5D.%0A%0ATo%20resolve%20this%2C%20the%20plugin%20needs%20to%20capture%20and%20replay%20the%20real%20%60thought_signature%60%20from%20Gemini%20API%20responses%20as%20described%20in%20the%20%5BGemini%20API%20documentation%5D%28https%3A//ai.google.dev/gemini-api/docs/thought-signatures%23model-behavior%29.%20For%20now%2C%20the%20only%20workaround%20is%20to%20use%20a%20different%20model%20%28like%20qwen-max%29%2C%20but%20this%20does%20not%20support%20Gemini-specific%20features%20%5B%5Bsource%5D%28https%3A//github.com/langgenius/dify-official-plugins/issues/2168%29%5D.%20If%20you%20need%20Gemini%20features%2C%20you%E2%80%99ll%20need%20to%20monitor%20plugin%20updates%20or%20consider%20contributing%20a%20patch%20that%20implements%20proper%20%60thought_signature%60%20handling.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify-official-plugins/issues/2492)
Author
Owner

@crazywoola commented on GitHub (Feb 3, 2026):

Hi @BeautyyuYanli, thanks for opening this issue.

Why this is being closed

Dify issue tracking requires English-only issue title and description for consistent collaboration.

Next steps

Please open a new issue in English and include clear details so maintainers can help efficiently.

Thanks for understanding and for your support.

@crazywoola commented on GitHub (Feb 3, 2026): Hi @BeautyyuYanli, thanks for opening this issue. ### Why this is being closed Dify issue tracking requires English-only issue title and description for consistent collaboration. ### Next steps Please open a new issue in English and include clear details so maintainers can help efficiently. Thanks for understanding and for your support.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify-official-plugins#948