-
-
Notifications
You must be signed in to change notification settings - Fork 69.3k
Context pruning skips image-containing tool results, causing unrecoverable context overflow in screenshot-heavy sessions #41789
Description
Bug Description
pruneContextMessages() in src/agents/pi-extensions/context-pruning/pruner.ts explicitly skips any toolResult message that contains image blocks:
if (hasImageBlocks(msg.content)) {
continue; // line ~248
}This means tool results with images (e.g. browser screenshots, read tool reading image files) can never be pruned, even when the context window is full. The comment says "for now" but there is no fallback or tracking issue.
Meanwhile, pruneProcessedHistoryImages() in src/agents/pi-embedded-runner/run/history-image-prune.ts only processes role === "user" messages — it does not touch toolResult images either.
Both pruning mechanisms ignore tool result images, creating a gap where screenshot-heavy sessions accumulate unbounded image data with no recovery path.
Impact
This is particularly severe for browser automation workflows — one of OpenClaw's core use cases. Each browser action can produce a screenshot as a toolResult. In a typical debugging session:
- 20 browser actions → 20 screenshot tool results
- Each image ~1200+ tokens (actual base64 data far larger)
pruneContextMessagescannot reclaim any of this space- Context window fills → session becomes unusable
Unlike user-uploaded images (#19099) or vision-model loops (#29290), this scenario has no workaround — the context pruner is supposed to be the safety net, but it refuses to touch the largest consumers of context space.
Reproduction
- Start a session with browser automation enabled
- Perform 15-20+ browser actions that produce screenshots
- Observe context usage growing monotonically
- Context pruning triggers but fails to free meaningful space (images skipped)
- Eventually: context overflow or severely degraded performance
Expected Behavior
pruneContextMessages() should be able to prune image-containing tool results, at minimum by replacing image blocks with a text placeholder like [screenshot removed during context pruning] while preserving any accompanying text content.
Suggested Fix
In softTrimToolResultMessage() and the hard-clear phase of pruneContextMessages(), instead of skipping image tool results entirely, replace image blocks with text placeholders:
// Instead of:
if (hasImageBlocks(msg.content)) {
continue;
}
// Consider:
if (hasImageBlocks(msg.content)) {
// Replace image blocks with placeholder, keep text blocks
const prunedContent = msg.content.map(block =>
block.type === 'image'
? asText('[image removed during context pruning]')
: block
);
// ... proceed with pruned content
}This preserves the message structure and any text descriptions while reclaiming the image data.
Related Issues
- [Bug]: Cumulative images in chat history cause HTTP 400 (Max images exceeded) on plain text messages #19099 — Cumulative user images cause HTTP 400 (different: user images, not tool results)
- Images in transcript poison session when model doesn't support vision (HTTP 400 loop) #29290 — Images poison session for non-vision models (different: model capability, not context overflow)
Environment
- OpenClaw: latest main branch
- Affected files:
src/agents/pi-extensions/context-pruning/pruner.ts(skips image tool results)src/agents/pi-embedded-runner/run/history-image-prune.ts(only handles user messages)