[BUG]: Gemini 3 Pro function calling fails - missing thoughtSignature support #3163

Closed
opened 2026-02-16 17:38:55 -05:00 by yindo · 21 comments
Owner

Originally created by @linhlban150612 on GitHub (Nov 27, 2025).

Originally assigned to: @rekram1-node on GitHub.

[BUG]: Gemini 3 Pro function calling fails - missing thoughtSignature support

Description

When using Gemini 3 Pro models (gemini-3-pro-preview) with function calling/tool use, requests fail with error:

Unable to submit request because function call `default_api:webfetch` in the 4. content block is missing a `thought_signature`.

Root Cause

Gemini 3 Pro requires thoughtSignature to be preserved and passed back during multi-step function calling. This is a mandatory validation introduced in Gemini 3 (unlike Gemini 2.5 where it was optional).

How Gemini 3 Thought Signatures Work

  1. When model responds with a functionCall, it includes a thoughtSignature field
  2. Client MUST preserve this signature and include it in the next request when sending functionResponse
  3. If signature is missing → API returns 400 error

Reference: https://ai.google.dev/gemini-api/docs/thought-signatures

Expected Flow

Turn 1, Step 1:
  Request: user_prompt
  Response: functionCall + thoughtSignature

Turn 1, Step 2:
  Request: user_prompt + (functionCall + thoughtSignature) + functionResponse  ← signature MUST be here
  Response: text_output or another functionCall + signature

Current Behavior in OpenCode

OpenCode does not preserve thoughtSignature from Gemini API responses when building subsequent requests in conversation history.

The contents array in requests to Gemini API is missing the thoughtSignature field in functionCall parts.

Affected Models

  • gemini-3-pro-preview (mandatory - will error)
  • gemini-2.5-pro / gemini-2.5-flash (optional but recommended for reasoning quality)

Proposed Fix

Option 1: Preserve thoughtSignature in Message History

When storing model responses that contain functionCall parts, also store the thoughtSignature field. When building the next request, include the signature in the corresponding content part:

{
  "contents": [
    {
      "role": "model",
      "parts": [
        {
          "functionCall": { "name": "webfetch", "args": {...} },
          "thoughtSignature": "<preserved_signature>"  // ← Add this
        }
      ]
    }
  ]
}

Option 2: Dummy Signature Workaround

According to Google's documentation, for cases where signatures cannot be preserved (e.g., transferring from another model), you can use dummy signatures:

"skip_thought_signature_validator"

or

"context_engineering_is_the_way_to_go"

This skips validation but may degrade reasoning quality.

Steps to Reproduce

  1. Configure opencode with Gemini 3 Pro (gemini-3-pro-preview)
  2. Ask a question that triggers tool/function calling (e.g., web search, file operations)
  3. When model makes a function call and receives response, the next request fails

Environment

  • OpenCode version: latest
  • Model: gemini-3-pro-preview
  • Provider: Google AI / Vertex AI

Additional Context

  • This issue affects any multi-step agentic workflow with Gemini 3
  • The Gemini CLI and official Google Gen AI SDKs handle this automatically via chat history management
  • OpenCode's custom provider/plugin architecture needs to explicitly handle this

Related Links

Originally created by @linhlban150612 on GitHub (Nov 27, 2025). Originally assigned to: @rekram1-node on GitHub. # [BUG]: Gemini 3 Pro function calling fails - missing `thoughtSignature` support ## Description When using Gemini 3 Pro models (`gemini-3-pro-preview`) with function calling/tool use, requests fail with error: ``` Unable to submit request because function call `default_api:webfetch` in the 4. content block is missing a `thought_signature`. ``` ## Root Cause Gemini 3 Pro **requires** `thoughtSignature` to be preserved and passed back during multi-step function calling. This is a **mandatory validation** introduced in Gemini 3 (unlike Gemini 2.5 where it was optional). ### How Gemini 3 Thought Signatures Work 1. When model responds with a `functionCall`, it includes a `thoughtSignature` field 2. **Client MUST preserve this signature** and include it in the next request when sending `functionResponse` 3. If signature is missing → API returns 400 error Reference: https://ai.google.dev/gemini-api/docs/thought-signatures ### Expected Flow ``` Turn 1, Step 1: Request: user_prompt Response: functionCall + thoughtSignature Turn 1, Step 2: Request: user_prompt + (functionCall + thoughtSignature) + functionResponse ← signature MUST be here Response: text_output or another functionCall + signature ``` ## Current Behavior in OpenCode OpenCode does not preserve `thoughtSignature` from Gemini API responses when building subsequent requests in conversation history. The `contents` array in requests to Gemini API is missing the `thoughtSignature` field in `functionCall` parts. ## Affected Models - `gemini-3-pro-preview` (mandatory - will error) - `gemini-2.5-pro` / `gemini-2.5-flash` (optional but recommended for reasoning quality) ## Proposed Fix ### Option 1: Preserve thoughtSignature in Message History When storing model responses that contain `functionCall` parts, also store the `thoughtSignature` field. When building the next request, include the signature in the corresponding content part: ```json { "contents": [ { "role": "model", "parts": [ { "functionCall": { "name": "webfetch", "args": {...} }, "thoughtSignature": "<preserved_signature>" // ← Add this } ] } ] } ``` ### Option 2: Dummy Signature Workaround According to Google's documentation, for cases where signatures cannot be preserved (e.g., transferring from another model), you can use dummy signatures: ``` "skip_thought_signature_validator" ``` or ``` "context_engineering_is_the_way_to_go" ``` This skips validation but may degrade reasoning quality. ## Steps to Reproduce 1. Configure opencode with Gemini 3 Pro (`gemini-3-pro-preview`) 2. Ask a question that triggers tool/function calling (e.g., web search, file operations) 3. When model makes a function call and receives response, the next request fails ## Environment - OpenCode version: latest - Model: `gemini-3-pro-preview` - Provider: Google AI / Vertex AI ## Additional Context - This issue affects any multi-step agentic workflow with Gemini 3 - The Gemini CLI and official Google Gen AI SDKs handle this automatically via chat history management - OpenCode's custom provider/plugin architecture needs to explicitly handle this ## Related Links - [Gemini Thought Signatures Documentation](https://ai.google.dev/gemini-api/docs/thought-signatures) - [Dify Plugin Fix for same issue](https://github.com/langgenius/dify-official-plugins/issues/2088)
yindo closed this issue 2026-02-16 17:38:55 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Nov 27, 2025):

This issue might be a duplicate of existing issues. Please check:

  • #4816: "Could not use model "Gemini 3 Pro Preview" of Github copilot provider: "invalid request body"" - Reports Gemini 3 tool calling failures with invalid request body errors in OpenCode
  • #4802: "tool_use ids were found without tool_result blocks" - Related to tool use/function calling message structure issues across multiple models

Both issues indicate problems with how OpenCode handles function calling/tool use responses from LLM providers, which is the core issue described here regarding thoughtSignature handling.

Feel free to ignore if none of these address your specific case.

@github-actions[bot] commented on GitHub (Nov 27, 2025): This issue might be a duplicate of existing issues. Please check: - #4816: "Could not use model "Gemini 3 Pro Preview" of Github copilot provider: "invalid request body"" - Reports Gemini 3 tool calling failures with invalid request body errors in OpenCode - #4802: "`tool_use` ids were found without `tool_result` blocks" - Related to tool use/function calling message structure issues across multiple models Both issues indicate problems with how OpenCode handles function calling/tool use responses from LLM providers, which is the core issue described here regarding `thoughtSignature` handling. Feel free to ignore if none of these address your specific case.
Author
Owner

@rekram1-node commented on GitHub (Nov 29, 2025):

I can't replicate issue with your reproduction steps

@rekram1-node commented on GitHub (Nov 29, 2025): I can't replicate issue with your reproduction steps
Author
Owner

@andreigiura commented on GitHub (Dec 2, 2025):

@rekram1-node i think this happens when using gemini 3 pro with openrouter

@andreigiura commented on GitHub (Dec 2, 2025): @rekram1-node i think this happens when using gemini 3 pro with openrouter
Author
Owner

@rekram1-node commented on GitHub (Dec 2, 2025):

what version of OC are you using

@rekram1-node commented on GitHub (Dec 2, 2025): what version of OC are you using
Author
Owner

@s16173760 commented on GitHub (Dec 6, 2025):

I suggest using this method first. https://github.com/langgenius/dify-official-plugins/pull/2120

@s16173760 commented on GitHub (Dec 6, 2025): I suggest using this method first. https://github.com/langgenius/dify-official-plugins/pull/2120
Author
Owner

@andreigiura commented on GitHub (Dec 10, 2025):

@rekram1-node i am using the latest version 1.0.141. The error i get is:
{"code":400,"message":"Provider returned error","type":null,"param":null,"metadata":{"raw":"{\n "error": {\n "code": 400,\n "message": "Corrupted thought signature.",\n "status": "INVALID_ARGUMENT"\n }\n}\n","provider_name":"Google AI Studio"}}

@andreigiura commented on GitHub (Dec 10, 2025): @rekram1-node i am using the latest version 1.0.141. The error i get is: {"code":400,"message":"Provider returned error","type":null,"param":null,"metadata":{"raw":"{\n \"error\": {\n \"code\": 400,\n \"message\": \"Corrupted thought signature.\",\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n","provider_name":"Google AI Studio"}}
Author
Owner

@rekram1-node commented on GitHub (Dec 10, 2025):

@andreigiura under what circumstances? Any reproduction steps?

@rekram1-node commented on GitHub (Dec 10, 2025): @andreigiura under what circumstances? Any reproduction steps?
Author
Owner

@andreigiura commented on GitHub (Dec 10, 2025):

@rekram1-node i have tried to build a hello world app. then tried to enhence its design. it builds the hello world with react for example, but at some point it fails and never recover. just need to work with it a little bit in order to reproduce it. it only happes on openrouter provider, not directly with google gemini

@andreigiura commented on GitHub (Dec 10, 2025): @rekram1-node i have tried to build a hello world app. then tried to enhence its design. it builds the hello world with react for example, but at some point it fails and never recover. just need to work with it a little bit in order to reproduce it. it only happes on openrouter provider, not directly with google gemini
Author
Owner

@rekram1-node commented on GitHub (Dec 10, 2025):

Oh well that makes sense then

@rekram1-node commented on GitHub (Dec 10, 2025): Oh well that makes sense then
Author
Owner

@rekram1-node commented on GitHub (Dec 10, 2025):

OpenRouter just did some bug fixes for their provider and I merged their fix in today. it will be in next release

@rekram1-node commented on GitHub (Dec 10, 2025): OpenRouter just did some bug fixes for their provider and I merged their fix in today. it will be in next release
Author
Owner

@matthewijordan commented on GitHub (Dec 14, 2025):

@rekram1-node have you got a link to the changes? I've just jumped to the latest release and I'm still seeing this issue

@matthewijordan commented on GitHub (Dec 14, 2025): @rekram1-node have you got a link to the changes? I've just jumped to the latest release and I'm still seeing this issue
Author
Owner

@rekram1-node commented on GitHub (Dec 14, 2025):

@matthewijordan you are encountering issues with gemini specifically through openrouter? Can you explain steps to reproduce?

@rekram1-node commented on GitHub (Dec 14, 2025): @matthewijordan you are encountering issues with gemini specifically through openrouter? Can you explain steps to reproduce?
Author
Owner

@rekram1-node commented on GitHub (Dec 14, 2025):

here is one of the last fixes they did:
https://github.com/OpenRouterTeam/ai-sdk-provider/pull/288

@rekram1-node commented on GitHub (Dec 14, 2025): here is one of the last fixes they did: https://github.com/OpenRouterTeam/ai-sdk-provider/pull/288
Author
Owner

@ramarivera commented on GitHub (Dec 23, 2025):

Not sure if related at all, but when using Zen + Gemini 3 Pro I get

Request contains an invalid argument.

on every request 🤔
Not sure where logs would get stored, but lemme know if I can provide more info?

@ramarivera commented on GitHub (Dec 23, 2025): Not sure if related at all, but when using Zen + Gemini 3 Pro I get ``` Request contains an invalid argument. ``` on every request 🤔 Not sure where logs would get stored, but lemme know if I can provide more info?
Author
Owner

@xmili233 commented on GitHub (Dec 26, 2025):

我遇到了同样的问题,有什么办法在本地解决吗?
Bad Request: {"error":{"message":"Corrupted thought signature.","type":"api_error","upstreamStatus":400,"upstreamStatusText":"Bad Request","upstreamResponse":{"error":{"code":400,"message":"Corrupted thought signature.","status":"INVALID_ARGUMENT"}}}}

@xmili233 commented on GitHub (Dec 26, 2025): 我遇到了同样的问题,有什么办法在本地解决吗? Bad Request: {"error":{"message":"Corrupted thought signature.","type":"api_error","upstreamStatus":400,"upstreamStatusText":"Bad Request","upstreamResponse":{"error":{"code":400,"message":"Corrupted thought signature.","status":"INVALID_ARGUMENT"}}}}
Author
Owner

@rekram1-node commented on GitHub (Dec 26, 2025):

@xmili233 what provider are you getting that with?

@rekram1-node commented on GitHub (Dec 26, 2025): @xmili233 what provider are you getting that with?
Author
Owner

@rekram1-node commented on GitHub (Dec 26, 2025):

@ramarivera are u still getting that?

@rekram1-node commented on GitHub (Dec 26, 2025): @ramarivera are u still getting that?
Author
Owner

@ramarivera commented on GitHub (Dec 27, 2025):

@ramarivera are u still getting that?

Haven't got it in a while

@ramarivera commented on GitHub (Dec 27, 2025): > @ramarivera are u still getting that? Haven't got it in a while
Author
Owner

@mvelbaum commented on GitHub (Dec 27, 2025):

@rekram1-node I got this a bunch of times today using openrouter with gemini 3 flash preview (opencode 1.0.203):

INFO  2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=google/gemini-3-flash-preview sessionID=ses_49fa166b4ffeO1i97cie96xdii small=false agent=build stream
INFO  2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=google/gemini-3-flash-preview sessionID=ses_49fa166b4ffeO1i97cie96xdii small=false agent=build params={"options":{"usage":{"include":true},"reasoning":{"effort":"high"}}} params
INFO  2025-12-27T15:14:34 +7ms service=bus type=session.status publishing
INFO  2025-12-27T15:14:34 +17ms service=bus type=message.updated publishing
INFO  2025-12-27T15:14:34 +1ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title stream
INFO  2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title params={"options":{}} params
INFO  2025-12-27T15:14:34 +8ms service=bus type=session.updated publishing
INFO  2025-12-27T15:14:34 +1ms service=bus type=session.diff publishing
ERROR 2025-12-27T15:14:35 +905ms service=default e=NotFoundError rejection
ERROR 2025-12-27T15:14:35 +164ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title error={"error":{"name":"AI_APICallError","url":"https://openrouter.ai/api/v1/chat/completions","requestBodyValues":{"model":"google/gemini-3-flash-preview","max_tokens":32000,"messages":[{"role":"system","content":"You are opencode, an interactive CLI agent specializing in software engineering tasks....................

<snipped>

,"responseBody":"{\"error\":{\"message\":\"Provider returned error\",\"code\":400,\"metadata\":{\"raw\":\"Gemini models require OpenRouter reasoning details to be preserved in each request. Please refer to our docs: https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#preserving-reasoning-blocks. Upstream error: {\\n  \\\"error\\\": {\\n    \\\"code\\\": 400,\\n    \\\"message\\\": \\\"Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:bash` , position 6. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.\\\",\\n    \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n  }\\n}\\n\",\"provider_name\":\"Google AI Studio\"}},\"user_id\":\"user_XXXXXX\"}","isRetryable":false,"data":{"error":{"code":400,"message":"Provider returned error","type":null,"param":null,"metadata":{"raw":"Gemini models require OpenRouter reasoning details to be preserved in each request. Please refer to our docs: https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#preserving-reasoning-blocks. Upstream error: {\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:bash` , position 6. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n","provider_name":"Google AI Studio"}},"user_id":"user_XXXXX"}}} stream error
ERROR 2025-12-27T15:14:35 +2ms service=session.processor error=Provider returned error stack="AI_APICallError: Provider returned error\n    at <anonymous> (../../node_modules/.bun/@openrouter+ai-sdk-provider@1.5.2+3b0e54cca049e8b1/node_modules/@openrouter/ai-sdk-provider/dist/index.mjs:821:18)\n    at processTicksAndRejections (native:7:39)" process
INFO  2025-12-27T15:14:35 +0ms service=bus type=session.error publishing

I had their new Response Healing feature enabled. Turned it off for now, will see if it had anything to do with it.

Edit: didn't help :(, am getting it again.

@mvelbaum commented on GitHub (Dec 27, 2025): @rekram1-node I got this a bunch of times today using openrouter with gemini 3 flash preview (opencode 1.0.203): ``` INFO 2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=google/gemini-3-flash-preview sessionID=ses_49fa166b4ffeO1i97cie96xdii small=false agent=build stream INFO 2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=google/gemini-3-flash-preview sessionID=ses_49fa166b4ffeO1i97cie96xdii small=false agent=build params={"options":{"usage":{"include":true},"reasoning":{"effort":"high"}}} params INFO 2025-12-27T15:14:34 +7ms service=bus type=session.status publishing INFO 2025-12-27T15:14:34 +17ms service=bus type=message.updated publishing INFO 2025-12-27T15:14:34 +1ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title stream INFO 2025-12-27T15:14:34 +0ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title params={"options":{}} params INFO 2025-12-27T15:14:34 +8ms service=bus type=session.updated publishing INFO 2025-12-27T15:14:34 +1ms service=bus type=session.diff publishing ERROR 2025-12-27T15:14:35 +905ms service=default e=NotFoundError rejection ERROR 2025-12-27T15:14:35 +164ms service=llm providerID=openrouter modelID=anthropic/claude-haiku-4.5 sessionID=ses_49fa166b4ffeO1i97cie96xdii small=true agent=title error={"error":{"name":"AI_APICallError","url":"https://openrouter.ai/api/v1/chat/completions","requestBodyValues":{"model":"google/gemini-3-flash-preview","max_tokens":32000,"messages":[{"role":"system","content":"You are opencode, an interactive CLI agent specializing in software engineering tasks.................... <snipped> ,"responseBody":"{\"error\":{\"message\":\"Provider returned error\",\"code\":400,\"metadata\":{\"raw\":\"Gemini models require OpenRouter reasoning details to be preserved in each request. Please refer to our docs: https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#preserving-reasoning-blocks. Upstream error: {\\n \\\"error\\\": {\\n \\\"code\\\": 400,\\n \\\"message\\\": \\\"Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:bash` , position 6. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.\\\",\\n \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n }\\n}\\n\",\"provider_name\":\"Google AI Studio\"}},\"user_id\":\"user_XXXXXX\"}","isRetryable":false,"data":{"error":{"code":400,"message":"Provider returned error","type":null,"param":null,"metadata":{"raw":"Gemini models require OpenRouter reasoning details to be preserved in each request. Please refer to our docs: https://openrouter.ai/docs/guides/best-practices/reasoning-tokens#preserving-reasoning-blocks. Upstream error: {\n \"error\": {\n \"code\": 400,\n \"message\": \"Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:bash` , position 6. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.\",\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n","provider_name":"Google AI Studio"}},"user_id":"user_XXXXX"}}} stream error ERROR 2025-12-27T15:14:35 +2ms service=session.processor error=Provider returned error stack="AI_APICallError: Provider returned error\n at <anonymous> (../../node_modules/.bun/@openrouter+ai-sdk-provider@1.5.2+3b0e54cca049e8b1/node_modules/@openrouter/ai-sdk-provider/dist/index.mjs:821:18)\n at processTicksAndRejections (native:7:39)" process INFO 2025-12-27T15:14:35 +0ms service=bus type=session.error publishing ``` I had their new Response Healing feature enabled. Turned it off for now, will see if it had anything to do with it. Edit: didn't help :(, am getting it again.
Author
Owner

@Phnmz commented on GitHub (Jan 6, 2026):

Just want to mention that i get the same error by using it with OAuth with the plugin "opencode-gemini-auth@latest" can you guys fix it?

@Phnmz commented on GitHub (Jan 6, 2026): Just want to mention that i get the same error by using it with OAuth with the plugin "opencode-gemini-auth@latest" can you guys fix it?
Author
Owner

@rekram1-node commented on GitHub (Jan 21, 2026):

believe this was fixed, if ur getting it w/ an external plugin tho, I suspect ur plugin is at fault

@rekram1-node commented on GitHub (Jan 21, 2026): believe this was fixed, if ur getting it w/ an external plugin tho, I suspect ur plugin is at fault
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#3163