Skip to content

fix(core): keep injected binary data intact when truncating tool responses - #30241

Open
dongs0104 wants to merge 1 commit into
google-gemini:mainfrom
dongs0104:fix/binary-injection-truncation
Open

dongs0104 wants to merge 1 commit into
google-gemini:mainfrom
dongs0104:fix/binary-injection-truncation

Conversation

@dongs0104

Copy link
Copy Markdown

Summary

Since #30180, read_file on an audio or video file larger than about 48 KB fails with 400 "Base64 decoding failed". truncateFunctionResponsePart walks the function response recursively. It also cuts the base64 inside __binary_injection__, before GeminiChat moves that data into its own user turn. This PR skips that key when truncating.

Details

  • The fix is one condition in truncateFunctionResponsePart, so all four callers are covered: createSuccessResult and createCancelledResult in tool-executor.ts, and the two in local-executor.ts.
  • fix(core): bound multi-part tool outputs and evict older multimodal inlineData #30180's memory bound for binary data still holds. collapseOlderFunctionResponses already replaces inlineData in older user turns with OMITTED_BINARY_MESSAGE, which includes the turn the injection is moved into. Nested images in functionResponse.parts were never truncated either, for the same reason.
  • New unit test: an injected 200 KB base64 payload is kept as is, and a 100 KB text field in the same response is still truncated. The test fails on main and passes with this change.

Related Issues

Fixes #30240

How to Validate

  1. Unit tests:

    npm test -w @google/gemini-cli-core -- src/utils/tool-utils.test.ts src/scheduler/tool-executor.test.ts src/agents/memory-leak-regression.test.ts
  2. Live check on Linux with Login with Google, -m gemini-3-flash-preview. The workspace holds a 3-second 440 Hz WAV (96,044 bytes), and the prompt is gemini -p "Use read_file on tone.wav, then tell me in one sentence what you hear":

    Build Result
    main e5d88fb2c 400 Base64 decoding failed
    main + fix(core): keep the synthetic binary ack so injected audio/video stays in its own turn #30230 400 Base64 decoding failed
    this PR 400 Requests ending with a model turn are not supported (read_file on audio/video returns 400 "Requests ending with a model turn are not supported" on Gemini 3: synthetic binary ack turn is stripped #30229)
    this PR + fix(core): keep the synthetic binary ack so injected audio/video stays in its own turn #30230 200: "I hear a continuous ... sine tone lasting for 3 seconds."

    With Gemini 3 models, audio and video need this PR and fix(core): keep the synthetic binary ack so injected audio/video stays in its own turn #30230 together. Each fixes a different step.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

https://claude.ai/code/session_01Sw78yR9Us3cqRudv2DDgdA

…onses

truncateFunctionResponsePart cut the base64 inside __binary_injection__,
so read_file on audio/video over ~48 KB sent undecodable inlineData and
the API returned 400 "Base64 decoding failed". Older binary turns are
already evicted by collapseOlderFunctionResponses.

Fixes google-gemini#30240
@dongs0104
dongs0104 requested a review from a team as a code owner November 11, 2026 14:46
@github-actions github-actions Bot added the size/s A small PR label Nov 11, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/S

  • Lines changed: 30
  • Additions: +29
  • Deletions: -1
  • Files changed: 2

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where large binary files (audio/video) processed via read_file were being corrupted by the recursive truncation logic in truncateFunctionResponsePart. By explicitly excluding the binary injection key from the truncation process, the change ensures that base64 data is not inadvertently mangled, preventing 'Base64 decoding failed' errors while maintaining memory constraints for other response fields.

Highlights

  • Preventing binary data corruption: Updated truncateFunctionResponsePart to skip the __binary_injection__ key during truncation, ensuring that base64-encoded binary data remains intact and decodable.
  • Regression testing: Added a new unit test in tool-utils.test.ts to verify that large binary payloads are preserved while standard text fields continue to be truncated correctly.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-cli gemini-cli Bot added the area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality label Nov 11, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the truncateFunctionResponsePart utility in packages/core/src/utils/tool-utils.ts to prevent the truncation of binary injections identified by BINARY_INJECTION_KEY. This ensures that base64 media data remains intact to avoid undecodable requests, while other text fields continue to be truncated as expected. A corresponding unit test has been added to tool-utils.test.ts to verify this behavior. I have no further feedback to provide as the implementation is clean and well-tested.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality size/s A small PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

read_file audio/video over ~48 KB fails with "Base64 decoding failed" since #30180

1 participant