Checks
SDK Language
TypeScript
Strands Version
1.4.0
Language Runtime Version
Bun 1.3.9
Operating System
macOS 15 (also reproduced in a Linux arm64 container)
Installation Method
npm registry via bun
Steps to Reproduce
Any tool that returns two or more images of the same format in one tool result makes the next Gemini request fail. Minimal repro:
import { Agent, ImageBlock, TextBlock, tool } from "@strands-agents/sdk";
import { GeminiModel } from "@strands-agents/sdk/models/google";
import { z } from "zod";
const twoImages = tool({
name: "two_images",
description: "Returns two PNG images",
inputSchema: z.object({}),
callback: () => [
new TextBlock("2 images attached"),
new ImageBlock({ format: "png", source: { bytes: pngBytesA } }),
new ImageBlock({ format: "png", source: { bytes: pngBytesB } }),
],
});
const agent = new Agent({ model: /* Gemini */, tools: [twoImages] });
await agent.invoke("Call two_images, then describe what you see.");
The tool executes fine; the follow-up model call (the one carrying the tool result) is rejected by the API.
Expected Behavior
The tool result round-trips to Gemini and the model sees both images.
Actual Behavior
Gemini rejects the request that carries the tool result:
{
"error": {
"code": 400,
"message": "Duplicate parts `image.png` in a function_response.parts is not allowed.",
"status": "INVALID_ARGUMENT"
}
}
Root cause: formatToolResultBlock in strands-ts/src/models/google/adapters.ts hardcodes the same displayName for every image part in a tool result:
parts.push({
inlineData: {
data: encodeBase64(c.source.bytes),
mimeType,
displayName: `image.${c.format}`, // <-- identical for every image of a given format
},
});
Gemini enforces unique part names within one function_response.parts, so any tool result with ≥2 same-format images is unsendable. Since most multi-image use cases emit a single format (e.g. rendered PDF pages as PNGs), this breaks the common case. Observed on gemini-3.1-pro-preview via Vertex AI.
Additional Context
The 400 is deterministic, so retry strategies (correctly) don't retry it - the agent run fails outright.
The documentBlock branch a few lines below has the same latent issue: it uses displayName: c.name, which collides when two attached documents share a name.
Possible Solution
Make the generated names unique per tool result, e.g. number them:
let imageIndex = 0;
// ...
displayName: `image-${imageIndex++}.${c.format}`,
We've verified this fix locally via a package patch: with unique names, the same multi-image tool result is accepted and the model describes all images correctly.
Checks
SDK Language
TypeScript
Strands Version
1.4.0
Language Runtime Version
Bun 1.3.9
Operating System
macOS 15 (also reproduced in a Linux arm64 container)
Installation Method
npm registry via bun
Steps to Reproduce
Any tool that returns two or more images of the same format in one tool result makes the next Gemini request fail. Minimal repro:
The tool executes fine; the follow-up model call (the one carrying the tool result) is rejected by the API.
Expected Behavior
The tool result round-trips to Gemini and the model sees both images.
Actual Behavior
Gemini rejects the request that carries the tool result:
Root cause:
formatToolResultBlockinstrands-ts/src/models/google/adapters.tshardcodes the samedisplayNamefor every image part in a tool result:Gemini enforces unique part names within one
function_response.parts, so any tool result with ≥2 same-format images is unsendable. Since most multi-image use cases emit a single format (e.g. rendered PDF pages as PNGs), this breaks the common case. Observed ongemini-3.1-pro-previewvia Vertex AI.Additional Context
The 400 is deterministic, so retry strategies (correctly) don't retry it - the agent run fails outright.
The
documentBlockbranch a few lines below has the same latent issue: it usesdisplayName: c.name, which collides when two attached documents share a name.Possible Solution
Make the generated names unique per tool result, e.g. number them:
We've verified this fix locally via a package patch: with unique names, the same multi-image tool result is accepted and the model describes all images correctly.