Saltar al contenido principal

Error de Thought Signature en Nano Banana 2: causa y 3 arreglos

El 400 «Image part is missing a thought_signature» salta al reenviar la imagen anterior sin su firma. Se evita con previous_interaction_id o el chat del SDK.

LaoZhang AI TeamPublicadoActualizado 11 min de lectura
En esta página
Una respuesta completa conserva la imagen y su firma para la siguiente edición multiturno

Si el segundo turno de una edición con Nano Banana 2 (gemini-3.1-flash-image) responde 400 INVALID_ARGUMENT con el mensaje «Image part is missing a thought_signature in content position 2, part position 1», el fallo no está en la clave ni en el prompt. Tu código ha reenviado la imagen que generó el modelo sin la firma de pensamiento (thought signature) que venía pegada a ella. Suele pasar cuando un framework guarda la imagen como archivo y rehace el historial con mensajes simples.

Hay tres arreglos documentados, de más cómodo a menos:

  1. Interactions API en modo con estado. Pasas previous_interaction_id en el segundo turno y el servidor conserva las firmas. Es el método que usa la guía de imágenes de Google.
  2. generateContent con el chat del SDK google-genai, o añadiendo al historial el content de la respuesta tal como llegó, sin reconstruirlo.
  3. Actualizar el framework que pierde la firma. En Vercel AI SDK, la versión 6.0.114 de ai corrigió las firmas de imagen; si tu herramienta todavía no las conserva, toca abrir un issue o rodearla.

No hay ninguna firma ficticia documentada para partes de imagen. El valor skip_thought_signature_validator que menciona Google vale solo para llamadas a funciones y como último recurso. Y si tu código aún usa gemini-3.1-flash-image-preview, cambia antes el ID: los modelos -preview de imagen se apagaron el 25 de junio de 2026 (tabla de retiradas de Google).

«Image part is missing a thought_signature»: qué parte del historial falla

El mensaje dice qué elemento del historial llegó sin firma. «Content position» es el turno dentro de contents y «part position» es la parte dentro de ese turno. En el caso publicado en el issue #12988 de Vercel AI SDK (marzo de 2026), el historial tenía tres mensajes: el prompt inicial («Draw an airplane»), la respuesta del asistente con la imagen ya generada y la nueva petición de edición. La posición de contenido 2 era esa respuesta del asistente y la parte 1, la imagen. La numeración empieza en 1, así que el error apunta directamente a la imagen que reenviaste sin su firma.

El mismo problema aparece con otros nombres según la interfaz:

Lo que vesDóndeQué significa
HTTP 400 INVALID_ARGUMENT, «Image part is missing a thought_signature…»generateContent, Nano Banana 2Una imagen del turno del modelo volvió sin su firma
finishReason: MISSING_THOUGHT_SIGNATUREgenerateContent«Request has at least one thought signature missing», según la referencia de la API
missing_thought_signatureInteractions API«The response is missing a required thought signature», en la lista de errores de Google
Firma «not valid» o «corrupted»Informes de desarrolladoresLa firma llegó, pero modificada

Este último caso tiene la misma raíz aunque el texto cambie. Si guardas la firma recortada, la conviertes a otro formato y no la restauras byte a byte, o la mueves a otra parte, el modelo deja de reconocerla. La regla de Google es devolverla exactamente como llegó y dentro de su parte original.

Reintentar la misma petición no sirve: el informe de Vercel marcaba el error como no reintentable (isRetryable: false) y el historial sigue siendo el mismo. Si el segundo turno responde 200 pero sin imagen, el problema es otro y está en Nano Banana no genera imagen en la API.

Qué es la firma de pensamiento y por qué Nano Banana 2 la exige

Google define las firmas de pensamiento como «representaciones cifradas del razonamiento interno del modelo», necesarias para mantener la continuidad de ese razonamiento entre turnos (guía de pensamiento de la API de Gemini). No puedes leerlas ni editarlas: solo guardarlas y devolverlas.

Los modelos de imagen de Gemini 3 piensan siempre. La guía de generación de imágenes dice que el proceso de pensamiento está activado por defecto y no se puede desactivar en la API, así que bajar el nivel de pensamiento no te libra de la firma. Dónde viaja depende de la interfaz:

  • generateContent: no hay bloques de pensamiento propios. La firma es un metadato de una parte: de una parte functionCall o de la última parte de la respuesta, ya sea texto o inlineData (la imagen).
  • Interactions API: la firma vive en los pasos de pensamiento (thought) y en los pasos de herramientas integradas como Google Search. Nunca va en tus entradas ni en la salida final del modelo.

Lo confuso es que la exigencia cambia de un modelo de imagen a otro. La documentación de Google Cloud sobre firmas dice que Gemini 3 valida las firmas con más rigor y responde 400 si falta una obligatoria. En cambio, para las partes que no son llamadas a funciones las da por recomendadas, no obligatorias, y aclara que Gemini 3 Pro Image (gemini-3-pro-image, Nano Banana Pro) no devuelve 400 aunque falte la firma. Esa página no dice nada de Nano Banana 2, pero el informe de Vercel sí lo muestra: el mismo flujo que funcionaba con gemini-2.5-flash-image fallaba con gemini-3.1-flash-image-preview en cuanto reenviaba la imagen sin firma. Tampoco conviene fiarse de la excepción de Pro: un informe del plugin de Dify de diciembre de 2025 muestra el mismo 400 «Image part is missing a thought_signature» con la versión preliminar de Nano Banana Pro.

En la práctica, un código que funcionaba con Nano Banana Pro o con el primer Nano Banana puede romperse al cambiar a Nano Banana 2 sin tocar nada más. gemini-2.5-flash-image se apagó el 2 de octubre de 2026, así que muchas migraciones se están topando ahora con este error. Google no documenta si el ID estable gemini-3.1-flash-image se comporta distinto del -preview; lo prudente es tratar la firma de cada imagen como obligatoria.

Tres rutas para conservar el contexto: Interactions con estado, chat del SDK e historial manual completo

Arreglo 1: Interactions API con previous_interaction_id

Con la Interactions API en modo con estado no tienes que manejar firmas. La guía de pensamiento lo describe así: la interacción queda guardada en el servidor (store: true), pasas previous_interaction_id en el turno siguiente y el servidor conserva todos los bloques de pensamiento y sus firmas. El ejemplo de edición multiturno de la guía de imágenes de Google sigue este patrón y no pasa store de forma explícita.

python
# Ejemplo sin ejecutar; requiere google-genai y GEMINI_API_KEY en el entorno
import base64
from google import genai

client = genai.Client()

turno1 = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Una taza de cerámica azul sobre una mesa de madera, luz de mañana",
)
with open("taza_v1.png", "wb") as f:
    f.write(base64.b64decode(turno1.output_image.data))

# El servidor recupera la imagen anterior y sus firmas a partir del id
turno2 = client.interactions.create(
    model="gemini-3.1-flash-image",
    input="Cambia la taza a color terracota. No toques nada más.",
    previous_interaction_id=turno1.id,
)
if turno2.output_image:
    with open("taza_v2.png", "wb") as f:
        f.write(base64.b64decode(turno2.output_image.data))

Entre turnos solo necesitas guardar turno1.id, no la imagen ni la firma. Esto encaja bien en aplicaciones web y flujos con colas, donde cada petición puede atenderla un proceso distinto.

Si prefieres llevar tú el historial (modo sin estado), la regla cambia: tienes que reenviar todos los bloques de pensamiento exactamente como llegaron, sin quitarlos ni modificarlos. Si usas Google Search, sus pasos llevan firmas propias y también hay que reenviarlas. Ten en cuenta que en imágenes un bloque de pensamiento puede llegar sin resumen de texto, solo con la firma. Un filtro que descarte los pasos «vacíos» elimina justo lo que hace falta.

Para la estructura completa de la Interactions API (formatos de respuesta, tamaños, precios) tienes la guía de la API de imágenes de Gemini.

Arreglo 2: generateContent con el chat del SDK o la respuesta intacta

Si tu código usa generateContent, la documentación de Google Cloud indica que los SDK oficiales gestionan las firmas automáticamente siempre que uses su historial de chat o añadas el contenido completo de la respuesta al siguiente envío. El ejemplo de edición multiturno de esa página usa el objeto chat:

python
# Ejemplo sin ejecutar
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("Una taza de cerámica azul sobre una mesa de madera")
r2 = chat.send_message("Cambia la taza a color terracota. No toques nada más.")

for part in r2.candidates[0].content.parts:
    if part.inline_data:
        with open("taza_v2.png", "wb") as f:
            f.write(part.inline_data.data)

Si necesitas controlar el historial (para guardarlo, recortarlo o repartirlo entre procesos), añade el content de la respuesta sin reconstruirlo:

python
# Ejemplo sin ejecutar
modelo = "gemini-3.1-flash-image"
config = types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"])

historial = [
    types.Content(role="user", parts=[types.Part(text="Una taza de cerámica azul sobre una mesa de madera")])
]
r1 = client.models.generate_content(model=modelo, contents=historial, config=config)

# La respuesta entra tal cual: la parte de imagen conserva su thought_signature
historial.append(r1.candidates[0].content)
historial.append(
    types.Content(role="user", parts=[types.Part(text="Cambia la taza a color terracota")])
)
r2 = client.models.generate_content(model=modelo, contents=historial, config=config)

El fallo típico es justo lo contrario: sacar los bytes de la imagen, guardarlos como PNG y en el turno siguiente montar un mensaje del modelo nuevo con ese archivo. Ese mensaje ya no tiene firma.

Si llamas a la API REST sin SDK, la parte de imagen del turno del modelo tiene que volver con su firma al lado, en la misma parte:

json
{
  "role": "model",
  "parts": [
    {
      "inlineData": { "mimeType": "image/png", "data": "IMAGE_BASE64" },
      "thoughtSignature": "SIGNATURE_FROM_RESPONSE"
    }
  ]
}

Las reglas de Google Cloud para hacerlo a mano son tres: devuelve cada firma dentro de su parte original, no fusiones una parte con firma con otra sin ella y no combines dos partes que tengan firma, porque las cadenas no se pueden unir. Si la respuesta trae texto e imagen en partes separadas, cópialas todas en el mismo orden.

Arreglo 3: tu framework pierde la firma (Vercel AI SDK, n8n, Dify)

Cuando el error aparece en una aplicación hecha con un framework, casi siempre es porque este guarda la respuesta como mensaje genérico (texto más archivo) y descarta los metadatos de Gemini.

Vercel AI SDK. El issue #12988 se cerró el 4 de marzo de 2026 con el cambio «fix missing support for image thought signatures», publicado en ai 6.0.114 y @ai-sdk/google 3.0.38. Según la descripción del cambio, hasta entonces el SDK no procesaba las firmas de imagen ni en streaming ni en useChat, y cualquier mensaje posterior a una imagen fallaba. Al día siguiente el autor del informe dijo que seguía viendo el mismo error tras actualizar, y el mantenedor le preguntó si había actualizado los dos paquetes. Por eso conviene actualizar ai y @ai-sdk/google a la vez y revisar también cómo guardas los mensajes. En el ejemplo que reprodujo el error, el mensaje del asistente se rehacía a partir del PNG guardado, y un archivo no puede llevar firma. Conserva los mensajes tal como los devuelve el SDK.

n8n y el plugin de Gemini de Dify. Hay informes de desarrolladores con el mismo síntoma. Revisa el registro de cambios del nodo o plugin que uses y actualízalo. Si sigue sin conservar las firmas, abre un issue con el texto exacto del error. Mientras tanto, una salida práctica es llamar a la Interactions API con un nodo HTTP y guardar entre ejecuciones solo el id de la interacción para pasarlo como previous_interaction_id.

Si ya no tienes la firma. Cuando el historial guardado solo conserva la imagen, empieza una conversación nueva y manda esa imagen como entrada tuya junto con la instrucción de edición, igual que en el ejemplo de edición con imagen de entrada de la guía de Google. Una imagen que va en tu turno es una entrada y no necesita firma. Pierdes el razonamiento que el modelo hizo sobre la versión anterior, pero la edición se puede hacer.

Streaming: la firma puede llegar al final en una parte vacía

En streaming, la firma no tiene por qué llegar junto a la imagen. La documentación de Google Cloud advierte que en respuestas sin llamadas a funciones la firma puede venir en una parte con texto vacío, y pide procesar todas las partes hasta que llegue finish_reason. En la Interactions API, el delta thought_signature es el último antes de step.stop.

El error clásico es acumular solo lo que tiene texto o imagen:

python
# Ejemplo sin ejecutar: conserva todas las partes, también las de texto vacío
partes = []
for chunk in client.models.generate_content_stream(
    model=modelo, contents=historial, config=config
):
    cand = chunk.candidates[0] if chunk.candidates else None
    if cand and cand.content and cand.content.parts:
        partes.extend(cand.content.parts)  # sin filtrar por part.text

historial.append(types.Content(role="model", parts=partes))

Un if part.text: o un if chunk.text: descarta la parte vacía que trae la firma, y el turno siguiente da el 400 aunque el resto del código sea correcto.

Conservar todas las partes del streaming, incluidas las vacías que pueden llevar firma

Firmas en llamadas a funciones y skip_thought_signature_validator

En flujos de agentes con modelos Gemini 3, la firma de las llamadas a funciones sí es obligatoria y su ausencia da 400. Las reglas de la documentación de Google Cloud son estas:

  • Si la respuesta contiene partes functionCall, la primera de cada paso lleva firma y debe volver exactamente como llegó.
  • En llamadas en paralelo solo la primera functionCall lleva firma. Devuelve primero todas las llamadas y después todas las respuestas (FC1 con firma, FC2, FR1, FR2). Si las intercalas (FC1, FR1, FC2, FR2) obtienes un 400.
  • En llamadas secuenciales se validan todos los pasos del turno actual. Un turno empieza con el último mensaje del usuario que no sea un functionResponse.
  • En la API Chat Completions de Google Cloud, la firma viaja en extra_content.google.thought_signature dentro de cada tool_call.

skip_thought_signature_validator es un valor que se pone como firma en partes functionCall que no generó la API, por ejemplo al traer historial de un modelo que no produce firmas. Google lo presenta como último recurso porque empeora el rendimiento del modelo. No está documentado para partes de imagen, y tampoco lo están otras cadenas «mágicas» que circulan por foros.

Preguntas frecuentes sobre la firma de pensamiento en Gemini

¿Puedo desactivar el pensamiento de Nano Banana 2 para no tener que devolver firmas?

No. En los modelos de imagen de Gemini 3 el pensamiento está activado por defecto y no se puede desactivar en la API. Cada respuesta puede traer firmas, y en Nano Banana 2 la de la imagen hay que devolverla si vas a reenviar esa imagen como turno del modelo.

¿Sirve una firma ficticia como context_engineering_is_the_way_to_go en la edición de imágenes?

No hay ninguna documentación de Google que lo respalde para imágenes. El único valor documentado es skip_thought_signature_validator, y solo para partes functionCall sin firma. Para imágenes usa uno de los tres arreglos o empieza una conversación nueva con la imagen como entrada.

¿Qué pasa si cambio de modelo a mitad de la conversación?

En la Interactions API sin estado, la guía de pensamiento pide reenviar igualmente los bloques de pensamiento del modelo anterior; el servidor se encarga de la compatibilidad. En generateContent, si el historial viene de un modelo sin firmas, las llamadas a funciones pueden marcarse con skip_thought_signature_validator como último recurso. Las imágenes antiguas conviene mandarlas como entrada del usuario.

¿Puedo guardar el historial en una base de datos y retomarlo días después?

Sí, siempre que guardes cada parte completa con su firma y la restaures sin alterarla. En Python, thought_signature son bytes: si los pasas a base64 para guardarlos en JSON, decodifícalos de vuelta antes de reenviarlos. Con la Interactions API en modo con estado basta con guardar el id de la última interacción.

¿Por qué con Nano Banana Pro no me salía este error?

Porque Google Cloud documenta que Gemini 3 Pro Image no devuelve 400 cuando falta la firma, aunque recomienda devolverla igual para no perder contexto. Nano Banana 2 sí rechazó la imagen sin firma en los informes publicados. Si tu código salía bien con Pro, revisa cómo reconstruye el historial antes de cambiar de modelo.

Si el problema no es la firma sino un 429, una respuesta vacía o un parámetro que no hace efecto, mira los demás errores de imagen de la API de Gemini. Si el fallo aparece en la app de Gemini y no en tu código, la referencia es Nano Banana no funciona en Gemini: 12 arreglos para errores de imagen.

Documentación oficial

Los parámetros de la solicitud, los precios y las reglas de cobro están en la documentación para desarrolladores de LaoZhang API: facturación y fallos en la generación de imágenes.

Aviso: laozhang.ai es un servicio propio. Sus precios son nuestra tarifa, no una comparación independiente.

Fuentes8

Páginas externas que cita esta guía, en el orden en que aparecen. Última actualización: 5 oct 2026.

  1. 1.tabla de retiradas de Googleai.google.dev/gemini-api/docs/deprecations
  2. 2.issue #12988 de Vercel AI SDKgithub.com/vercel/ai/issues/12988
  3. 3.referencia de la APIai.google.dev/api/generate-content
  4. 4.lista de errores de Googleai.google.dev/gemini-api/docs/api-errors
  5. 5.guía de pensamiento de la API de Geminiai.google.dev/gemini-api/docs/thinking
  6. 6.guía de generación de imágenesai.google.dev/gemini-api/docs/image-generation
  7. 7.documentación de Google Cloud sobre firmasdocs.cloud.google.com/gemini-enterprise-agent-platform/models/thinking/thought-signatures
  8. 8.informe del plugin de Dify de diciembre de 2025github.com/langgenius/dify-official-plugins/issues/2262
Recuperación de Nano Banana 2 ante 503 con reintentos limitados, tarea pendiente e imagen final comprobada
Resolución de problemas

Nano Banana 2: qué hacer ante el error 503 «Model is overloaded»

Si Nano Banana 2 devuelve un 503 «Model is overloaded», reintenta con esperas variables y un límite total. Cuando ese límite se agota, conserva la tarea para después; una respuesta 200 solo cuenta como éxito si contiene una imagen utilizable.

10 min