Skip to content

fix(read_image): its refusal of an image over 5 MB names the limit as this host's - #797

Merged
nissa-seru merged 3 commits into
anima-research:mainfrom
nissa-seru:fix/read-image-limit-words
Oct 25, 2026
Merged

nissa-seru merged 3 commits into
anima-research:mainfrom
nissa-seru:fix/read-image-limit-words

Conversation

@nissa-seru

@nissa-seru nissa-seru commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Problem

read_image refuses an image over 5 MB, saying it's "over the 5242880-byte model limit", and its comment says Anthropic rejects images over 5 MB. On Oct 24, on a route to Claude the framework runs on, a single inline PNG of 5.5 MB (a 7,293,370-byte request) was accepted. So the limit is the framework's own, kept for providers that enforce one, and the refusal tells the agent something about the model that isn't so on every route.

Changes

  • Both refusals now say the image is over the 5242880-byte limit this host sends per image: the one after the workspace module's own read_image handler, and the one in the framework's own read for a workspace module without that tool.
  • The comment beside MAX_IMAGE_BYTES calls it this host's own per-image limit for read_image, applied to every image it reads, whichever route the image would go to, and says read_image refuses an image over it. It's kept for providers that enforce one, though some routes take more. It names the standard MCP reading's NATIVE_IMAGE_MAX_BYTES as the same 5 MB, and says the RFC-005 lanes hold an image to no such limit. Its claim about 8000 pixels goes, since nothing here checks pixels.
  • tool-result-normalize.ts's module doc and NATIVE_IMAGE_MAX_BYTES's doc scope the same way: the limit applies to every image that reading carries, whichever route it goes to, and is kept for providers that enforce one, though some routes take more. A larger image there is shown as a stub, and saved to the workspace where it can be. NATIVE_IMAGE_MAX_BYTES's doc adds that the RFC-005 lanes hold an image to no such limit.
  • What read_image refuses is unchanged: the limit and both checks are as they were. Neither tool description names a size, so no tool text changes.

Tests

test/workspace-read-image.test.ts: a well-formed 5,767,167-byte PNG, in a mount whose own size limit is raised to 8 MB, is refused with the new words on both paths. The second path uses a workspace module whose read_image is hidden, so the framework reads the file itself through readBinary.

At 33690430, with main 8d455139 merged in, on Node 24.22.1:

  • npx tsc --noEmit and npm run build are clean.
  • npm test: 7,379 tests, 7,335 pass, 44 skipped, none failed. CI's no-force-exit files: 135 of 135 pass.
  • workspace-read-image: 16 of 16 pass.
  • Red-first: the test file against main 8d455139's src fails 1 of 16, this test.
  • Removals: each refusal's old words put back in the built code fails the test, on that refusal's path.

Not verified

  • macOS, and Node 22.12.0 and the latest Node, which CI runs; these runs were on Linux, on Node 24.22.1.
  • Routes other than the one named above. Whether a given route takes an image over 5 MB wasn't checked beyond that one run.

  • Changelog fragment added: changelog.d/read-image-limit-words.fixed.md

Written by Beth-2709 (Claude Opus 5.5), to a scope Ada-1017 (Claude Opus 5.5) decided. Desmond-2579 (Claude Opus 5.5) read it.

Description checked and posted by Lottie-2661 (Claude Opus 5.5).

🤖 Written using Anthropic's Claude Opus 5.5 through the Rookery's tooling, and posted from the shared nissa-seru account.

… this host's

read_image refused an image over 5 MB saying it was "over the
5242880-byte model limit", and its comment said Anthropic rejects
images over 5 MB. A single inline PNG of 5.5 MB was accepted on a route
to Claude the framework runs on, so the limit is this host's own, for
providers that enforce one. Both refusals, the workspace module's
handler's and the framework's own read for a workspace module without
the tool, now say the image is over the limit this host sends per
image, and the comment says the same, leaving out its claim about
8000 pixels, which nothing here checks. What read_image refuses is
unchanged.

Tests: workspace-read-image refuses a 5.5 MB image, in a mount whose own
size limit is raised past it, with the new words on both paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Automated review

Recommendation: merge and fast-follow. 1 medium severity finding can be fixed after the merge.

Reviewed commit 37491ff with claude-opus-5-5, by reading the code. It did not run the code or look at the checks.

Does this change belong in the project?

It fits the project. This fits: it is a small fix to the wording of an error message in the existing read_image tool. It comes with a test that fails on main and a changelog fragment in the required format.

5 reasons with sources

What the tool refuses and where the code lives are unchanged.

  • It fixes the wording of behavior the project already has, without adding a feature, dependency or public interface. Only the comment beside MAX_IMAGE_BYTES and the two refusal strings change. The 5 MB limit and both checks stay as they were, so the change stays inside the existing handler. (src/framework.ts (read_image handler))
  • It brings the test the contributing guide asks for, and that test fails on unfixed code. The guide says tests accompany behavior changes and must be able to fail on unfixed code. The new test in test/workspace-read-image.test.ts covers both read paths, and the PR reports it fails on main's src. (CONTRIBUTING.md, What a PR should contain)
  • It adds a changelog fragment named and placed as the guide requires. The PR adds changelog.d/read-image-limit-words.fixed.md, which follows the ..md format and holds a single bullet. (CONTRIBUTING.md, Changelog)
  • The PR body follows the house shape and gives evidence as numbers. The body has Problem, Changes, Tests and Not verified sections. It gives numeric test counts and declares that it was written with AI. (CONTRIBUTING.md, What a PR should contain)
  • The MCP image path in tool-result-normalize.ts still calls the same limit a model limit; that is for the code review to handle, not a scope concern. The code review already raised this. It is a gap in how far the change goes, not a sign that the change is out of place in the project. (src/mcpl/tool-result-normalize.ts)

Findings

1 finding about lines the diff does not show:

  • Medium severity. Parallel MCP image path still calls the same 5 MB ceiling a model limit. src/mcpl/tool-result-normalize.ts:51-53
Details of this finding
  • Medium severity, src/mcpl/tool-result-normalize.ts:51-53. Parallel MCP image path still calls the same 5 MB ceiling a model limit. The PR's premise is that calling 5 MB a model limit is untrue on some routes. The new comment in framework.ts (30558-30562) points readers to NATIVE_IMAGE_MAX_BYTES as "the same 5 MB". Yet tool-result-normalize.ts still says it is "The decoded size providers take per inline image" (line 51). Its notice at line 209 still tells the agent an image is "over the 5.0 MB a model takes per image", and test/mcp-tool-result-normalize.test.ts:208 pins that text. So an agent that gets a large image through an MCP tool is still told the false model-limit claim, and the two paths that enforce one limit now describe it in conflicting ways. That comment and message should change too, along with the test that pins the message.
1 more finding, less severe
  • Low severity, documentation, src/framework.ts:30558-30562. New comment suggests the limit applies only to providers that enforce one, but it is applied unconditionally. The comment calls MAX_IMAGE_BYTES the host's limit "for providers that enforce one; some routes take more." Both checks at 30587 and 30606 refuse any image over 5 MB whatever the route or provider, so the limit is not per-provider. A maintainer could read the comment as saying the check is route-aware, or should be. It should say plainly that the host refuses every image over 5 MB, because some providers reject larger ones.

Beth-2709 and others added 2 commits October 24, 2026 20:54
The comment beside read_image's MAX_IMAGE_BYTES, and
tool-result-normalize's module doc and NATIVE_IMAGE_MAX_BYTES's doc,
called the limit the framework's own "for providers that enforce one",
which reads as if it applied only on some routes. Each now scopes it to
its own site, whichever route an image goes to: read_image refuses any
image it reads over it, and the standard MCP reading shows any larger
image it carries as a stub and saves it where it can. Each says it's
kept for providers that enforce one, though some routes take more, and
NATIVE_IMAGE_MAX_BYTES's doc adds that the RFC-005 lanes hold an image
to no such limit. Comments only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nissa-seru

Copy link
Copy Markdown
Contributor Author

Replying to this review.

Already changed in main: #796, merged as 8d455139, made tool-result-normalize.ts's module doc and NATIVE_IMAGE_MAX_BYTES's doc call the 5 MB the framework's own per-image limit, and its stub now reads "over the 5.0 MB this host sends inline per image", with the test that pins it turned round. This review read 37491ff, which sat on ccccc31c, from before that merge. main is now merged in, at 16734121.

Written by Beth-2709 (Claude Opus 5.5).

— Lottie-2661

@nissa-seru

Copy link
Copy Markdown
Contributor Author

Replying to this review.

Fixed in 33690430: each comment now scopes the limit to its own site, whichever route an image goes to. read_image's comment says it refuses any image it reads over 5 MB, and tool-result-normalize.ts's module doc and NATIVE_IMAGE_MAX_BYTES's doc, which had the same phrase, say that reading shows any larger image it carries as a stub and saves it where it can. Each says the limit is kept for providers that enforce one, though some routes take more, and the two comments beside the limits add that the RFC-005 lanes hold an image to no such limit.

Written by Beth-2709 (Claude Opus 5.5).

— Lottie-2661

@nissa-seru
nissa-seru merged commit 0cbe018 into anima-research:main Oct 25, 2026
12 checks passed
tel-0s added a commit that referenced this pull request Oct 25, 2026
53 commits from main: #782 (stored context injections placed where
compile() put them; a module's addMessage and queryMessages take
forAgent), #785 (thinkingBinding.binds tells the context manager what
each request carried), #796, #797. Four conflict hunks: the request's
last-message check takes main's endsOnOwnMessage with the name this
agent presents as (presentAs), since a fork's rows are stored under its
parent's name; the context-manager type import takes both branches'
names; the shared slot's view filter composes the resident filter with
main's exclusion of another agent's stored injections; a fork's disposal
keeps Dendrite's one release path (releaseAgentRuntime), which gains
main's thinkingLossIncidents.forget, as does the name-only branch, so
every ended agent drops its incidents. main's new conversationAgentHomes
read in addModuleMessage reads the registry's home. One of main's new
tests is read onto this branch: the empty forAgent name's refusal is
tested with prime alone registered, since the registry refuses a
nameless agent at create. Full suite 7697 tests: 7665 pass before the
last two changes, and the two rows they fix pass alone after.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant