Skip to content

[BUG] Gemini rejects tool results with multiple same-format images: duplicate displayName in function_response.parts (400 INVALID_ARGUMENT) #2748

Description

@Jarvvski

Checks

  • I have updated to the latest minor and patch version of Strands
  • I have checked the documentation and this is not expected behavior
  • I have searched ./issues and there are no duplicates of my issue

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-modelRelated to models or model providersarea-toolTool behavior/apibugSomething isn't workingtypescriptPull requests that update typescript code

    Type

    Fields

    Language

    TypeScript

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions