Nano Banana 2 Thought Signature 错误:上一张图丢了签名怎么修
Nano Banana 2 第二轮改图报 400,是上一张图被重发时丢了思考签名。改用 previous_interaction_id 续写,或把 content 原样放回历史。
文章目录

Nano Banana 2(gemini-3.1-flash-image)第一轮出图正常,第二轮改图却返回 400 INVALID_ARGUMENT,报错里写着 Image part is missing a thought_signature:原因几乎都是你把上一轮模型生成的图片重新发回去时,附在那张图片上的思考签名没有一起带上。修法按省事程度排有三种:用 Interactions API 的 previous_interaction_id 续写,签名由服务端保存;继续用 generateContent 的话,用 SDK 的 chat 对象,或把模型返回的 content 原样追加进历史;问题出在框架或平台时,升级到已修复的版本,或者把上一张图当作新上传的图片重开一轮。
这个错误跟 API 密钥、配额和模型 ID 都无关,换 key 或重试不会好转,同一个请求重发多少次都是 400。
Image part is missing a thought_signature 指哪一张图
一份公开的开发者报告(Vercel AI SDK issue #12988,2026 年 3 月 2 日,模型为当时的 gemini-3.1-flash-image-preview)贴出了完整返回:
{
"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"
}
}那次请求的历史只有三条:用户的第一句、模型上一轮的回复(一张图片)、用户的第二句。对照下来,content position 2 是模型那一轮,part position 1 是其中第一个 part,也就是上一张生成的图片。换成你自己的请求,按这两个位置去数,就能找到是哪一轮、哪个 part 少了签名。
报错里给的 thought-signatures 链接现在会跳到 Google 的 Gemini 思考文档,签名的说明都在那一页。如果你用的是 Interactions API,同类问题在错误码列表里叫 missing_thought_signature,说明是“response is missing a required thought signature”。
思考签名是什么:附在 part 上的加密推理状态
Google 的思考文档把思考签名定义为模型内部推理的加密表示,多轮交互要靠它保持推理连贯。Nano Banana 2 和 Nano Banana Pro 都属于 Gemini 3 图片模型,生成前会先推理,过程中还会产生不计费的中间“思考图片”,签名记下的就是这一轮推理的状态。
签名放在哪里,取决于你调用的是哪个接口:
| 接口 | 签名的位置 | 你要做的事 |
|---|---|---|
| Interactions API(有状态,默认) | 服务端保存的思考步骤里 | 下一轮传 previous_interaction_id,不用碰签名 |
| Interactions API(无状态) | thought 步骤和内置工具的调用、结果块里 | 把收到的思考块原样全部发回,不删不改 |
| generateContent | 作为元数据挂在某个 part 上:functionCall part,或回复的最后一个 part(文本或图片) | 把模型那一轮的 part 原样放回 contents |
第三行是多轮改图出错的根源。Google Cloud 的思考签名文档写明,回复的最后一个 part 可以是文本,也可以是 inlineData,签名可能就挂在图片 part 上。你回放历史时如果只放回图片字节,生成的是一个“内容相同、但没有签名”的新 part,模型就无法确认这是它自己生成过的内容。
为什么第一轮正常、第二轮改图才报 400
第一轮请求里没有模型生成的内容,用不到签名。到了第二轮,你的历史里第一次出现模型生成的 part,签名缺失才会被检查出来。
签名最常丢在“通用消息格式”里。很多框架和聊天平台把对话存成“角色 + 文本 / 文件”的结构,图片存成文件或 base64,下一轮再拼成新的 part;签名不属于这种结构,保存时就已经丢了。前面那份 Vercel 报告的复现代码就是这样:助手消息里只有 type、data、filename、mediaType 四个字段,报告者还提到同样的流程在 gemini-2.5-flash-image 上一直正常。Dify 的 Gemini 插件也有同样的报告(dify-official-plugins #2262,2025 年 12 月),报错文本与上面一字不差。
gemini-2.5-flash-image 已于 2026 年 10 月 2 日停用,gemini-3.1-flash-image-preview 和 gemini-3-pro-image-preview 也已于 2026 年 6 月 25 日停用(Google 停用时间表)。现在能用的 Nano Banana 2 是 gemini-3.1-flash-image,Nano Banana Pro 是 gemini-3-pro-image,旧代码迁过来时,多轮历史的处理方式要按下面的修法一起改。
Nano Banana Pro 不报错、Nano Banana 2 报错:两种模型的校验差异
Google Cloud 的思考签名文档写:Gemini 3 模型对签名的校验比以前的版本严格,缺了必需的签名会返回 400;但 Gemini 3 Pro Image 不执行这项校验,缺签名不会返回 400,只是仍然应该回传,模型才能保持多轮上下文。同一页还写,不在 functionCall 上的签名属于“建议回传、省略不会报错”。
Nano Banana 2 的行为,这页文档没有单独写。开发者报告显示,它对图片 part 的签名会直接返回 400。所以在 Nano Banana Pro 上跑得通的多轮改图代码,换成 Nano Banana 2 就可能在第二轮失败,代码本身没变。
反方向的证据也有:上面那份 Dify 报告用的是 2025 年 12 月的 Nano Banana Pro 预览版,同样在第二张图上收到了这条 400。文档和报告并不完全一致,稳妥的做法是不按模型区分:凡是模型生成的 part,都带着签名原样放回去。

修法一:Interactions API 传 previous_interaction_id
Google 图片生成指南(2026 年 9 月 23 日更新)的多轮改图示例走的就是这条路:第一轮正常创建 interaction,第二轮用 previous_interaction_id 指向它。思考文档对这种有状态模式的说明是,服务端自动管理对话状态,包括所有思考块和签名,“你不需要做任何事”。
下面几段代码按 Google 2026 年 10 月的文档写成,没有实际调用 API 运行过。genai.Client() 会从环境变量 GEMINI_API_KEY 读取密钥。
import base64
from google import genai
client = genai.Client()
MODEL = "gemini-3.1-flash-image" # Nano Banana 2
first = client.interactions.create(
model=MODEL,
input="画一架停在草地上的白色小飞机,扁平插画风格",
)
with open("v1.png", "wb") as f:
f.write(base64.b64decode(first.output_image.data))
# 第二轮:不重发图片,只引用上一轮的 interaction
second = client.interactions.create(
model=MODEL,
input="在机翼上加一只长颈鹿,其他元素保持不变",
previous_interaction_id=first.id,
)
if second.output_image:
with open("v2.png", "wb") as f:
f.write(base64.b64decode(second.output_image.data))这种写法的前提是 interaction 保存在服务端(store 保持默认的 true)。如果你出于数据保留要求关掉了 store,就进入无状态模式,要自己把完整历史发回去。这时文档的要求很明确:收到的所有思考块必须原样重发,不能删、不能改;Google 搜索这类内置工具的调用和结果块带有各自的签名,也要一起回传。中途换模型时,之前那个模型的思考块照样回传,兼容由后端处理。
修法二:generateContent 用 chat,或原样追加 content
继续用 generateContent 也能修好。Google Cloud 文档的说法是:用官方 Gen AI SDK(Python、Node.js、Go、Java)的 chat 历史功能,或者把模型上一轮返回的完整 content 追加进历史,签名会自动处理。
最省事的是 chat 对象:
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"]),
)
chat.send_message("画一架停在草地上的白色小飞机,扁平插画风格")
r2 = chat.send_message("在机翼上加一只长颈鹿,其他元素保持不变")
for part in r2.candidates[0].content.parts:
if part.inline_data:
with open("v2.png", "wb") as f:
f.write(part.inline_data.data)需要自己管理 contents 时,关键是追加 response.candidates[0].content 这个对象本身,而不是从里面取出图片再拼一个新的 part:
config = types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"])
contents = [
types.Content(role="user", parts=[types.Part(text="画一架停在草地上的白色小飞机,扁平插画风格")])
]
r1 = client.models.generate_content(
model="gemini-3.1-flash-image", contents=contents, config=config
)
# 正确:原样追加,签名留在原来的 part 上
contents.append(r1.candidates[0].content)
# 错误:只剩图片字节,签名丢了,下一轮会 400
# img = r1.candidates[0].content.parts[-1].inline_data.data
# contents.append(types.Content(role="model", parts=[types.Part.from_bytes(data=img, mime_type="image/png")]))
contents.append(
types.Content(role="user", parts=[types.Part(text="在机翼上加一只长颈鹿,其他元素保持不变")])
)
r2 = client.models.generate_content(
model="gemini-3.1-flash-image", contents=contents, config=config
)对话要存进数据库、下次再接着改时,存的应该是模型那一轮完整的 content,每个 part 连同它的 thoughtSignature 字段一起保存,读回时原样放回;只存图片文件,下次就只能当作新图片上传。Google Cloud 文档另有三条手写历史时的规则:签名要放在它原来的 part 里发回;不要把带签名的 part 和不带签名的 part 合并;也不要把两个都带签名的 part 合成一个,签名字符串没法合并。
用流式接口自己拼历史时还要多看一步。Google Cloud 文档提醒,流式输出时签名可能出现在一个文本为空的 part 里,要把所有 part 一直解析到返回 finish_reason 为止。实践上,按 if chunk.text: 过滤 chunk 的写法会把这个空文本 part 连同签名一起跳过;保留每个 chunk 里的全部 part,再组装模型那一轮,就不会漏掉。

修法三:Vercel AI SDK、Dify、n8n 丢签名时升级或绕开
签名丢在你改不动的代码里时,先看框架有没有修过:
- Vercel AI SDK:issue #12988 对应的修复“fix missing support for image thought signatures”已发布在
ai6.0.114 和@ai-sdk/google3.0.38,两个包都要升级。同一个 issue 里,报告者升级后仍然收到同样的报错;从他的复现代码看,助手消息是用保存下来的图片文件重新拼出来的,里面本来就没有签名,SDK 也补不回来。升级之后,让 SDK 回放它自己返回的消息,不要用图片文件重建助手消息(这一点是根据复现代码的推断)。 - Dify:上面的 #2262 已于 2026 年 1 月 6 日以“不计划处理”关闭。插件后来的版本是否支持图片签名,issue 里没有说明,升级插件后先用两轮改图测一次。
- n8n:公开报告主要集中在 AI Agent 节点调用工具时缺签名,例如 #23798 和 #31303,两者都在 2026 年 7 月 14 日关闭,先把 n8n 升到这之后的版本。#35393(2026 年 8 月,Vertex 上的
gemini-3.5-flash接工具后报 400,去掉工具就正常)截至 2026 年 10 月 5 日仍未关闭,那份报错只有一句“Google request failed with status code 400”,没写是不是签名问题。
暂时改不了框架时,还有一条退路:把上一张图当作你自己上传的参考图,和修改要求一起发一个新的单轮请求。签名只附在模型生成的内容上,你上传的图片不需要签名,所以不会触发这条 400;代价是模型拿不到上一轮的推理,多次连续修改时风格和细节的一致性可能变差。
Function call is missing a thought_signature:函数调用的签名规则
用 Gemini 3 模型做工具调用或 Agent 流程时,同类报错写作 Function call is missing a thought_signature in functionCall parts,Dify 和 n8n 的 issue 标题里都出现过。函数调用的规则比图片更严,Google Cloud 文档写的是:
| 情况 | 签名在哪 | 怎么回传 |
|---|---|---|
| 一步里只调一个函数 | 这个 functionCall part 上 | 连同 part 原样放回,再接 functionResponse |
| 一轮里先后调多个函数(顺序调用) | 每一步的第一个 functionCall part 上 | 当前这一轮所有步骤都会校验,任何一步缺签名都是 400 |
| 一步里同时调多个函数(并行调用) | 只有第一个 functionCall part 带签名 | 顺序必须是全部调用在前、全部结果在后:FC1(带签名)、FC2、FR1、FR2;交错成 FC1、FR1、FC2、FR2 会 400 |
“一轮”从最近一条不是 functionResponse 的用户消息算起。即使把思考等级调到最低(MINIMAL),签名照样要回传。
通过 Vertex 上的 Chat Completions 兼容接口调用时,签名放在每个 tool_calls 元素的 extra_content.google.thought_signature 里,回传助手消息时这个字段要保留在原来的 tool call 上。
skip_thought_signature_validator 能跳过图片签名吗
不能这样用。Google Cloud 文档里,skip_thought_signature_validator 只用于一种少见情况:你要提供的 functionCall part 不是 API 生成的,所以没有签名,例如从不产生签名的其他模型迁移过来的对话历史。这时可以把 thought_signature 设成这个字符串,但文档同时写明它是最后手段,会降低模型表现。
文档没有说它能用在图片 part 上,也没有给图片准备任何占位签名。多轮改图报 400 时,应该回到前面三种修法,让真实的签名回到历史里;确实找不回签名的旧对话,就用“把图片当作新上传的参考图”那条退路重新开始。
Corrupted thought signature:签名在,但被改动过
报错如果是 Corrupted thought signature 或 signature is not valid 这一类,而不是 missing,通常说明字段还在,只是内容已经不是模型发出的原样(这是从报错文字作出的判断,文档没有逐条列出原因)。照着前面的规则可以排查几处:自己序列化和反序列化时,签名有没有被重复编码或截断;有没有把带签名的 part 和别的 part 合并;有没有把别的对话、别的轮次的签名挪到这里。最省事的还是改用修法一或修法二,不手动搬运签名。
如果你的请求返回 200 却没有图片,要查的是另一组字段,见 Nano Banana API 不出图的排查;429、参数报错等其他接口问题,见 Gemini 图片生成错误的分类修复。还没写过第一段调用代码,可以从 Gemini 图片 API 的现役模型 ID 与 Python 代码开始。在 Gemini 应用里出图失败、提示 Something went wrong,属于应用端的问题,分别见 Nano Banana 无法生成图片的修复分支和 Nano Banana Pro 错误 5。
官方文档
接入参数、价格与扣费规则以老张API开发文档为准:图片生成计费与失败处理。
说明:laozhang.ai 是我们自己的服务,其价格是平台报价,不是独立比较的结论。
参考来源9
本文引用的外部页面,按正文出现顺序排列。最后更新于 2026年10月5日。
参考来源9
本文引用的外部页面,按正文出现顺序排列。最后更新于 2026年10月5日。
- 1.Vercel AI SDK issue #12988github.com/vercel/ai/issues/12988
- 2.Gemini 思考文档ai.google.dev/gemini-api/docs/thinking
- 3.错误码列表ai.google.dev/gemini-api/docs/api-errors
- 4.思考签名文档docs.cloud.google.com/gemini-enterprise-agent-platform/models/thinking/thought-signatures
- 5.dify-official-plugins #2262github.com/langgenius/dify-official-plugins/issues/2262
- 6.Google 停用时间表ai.google.dev/gemini-api/docs/deprecations
- 7.#23798github.com/n8n-io/n8n/issues/23798
- 8.#31303github.com/n8n-io/n8n/issues/31303
- 9.#35393github.com/n8n-io/n8n/issues/35393





