Bug
When an image enters the session transcript (webchat upload, tool result, etc.) and the model provider does not support vision, the session enters an unrecoverable error loop:
- Image is persisted in transcript as a user turn
- Model rejects the request (HTTP 400: "vision is not enabled for this organization")
- No assistant reply is saved (due to the error)
pruneProcessedHistoryImages() only strips images from turns before the last assistant reply — since no assistant reply was saved, the image turn is never pruned
- Every subsequent message re-sends the image → 400 forever
- Only fix is
/new or /reset
Root Cause
Two issues:
-
No vision-gating on transcript images: Even when modelHasVision is false (model resolves with input: ["text"]), image blocks in the transcript are still sent to the provider. There is no step that strips image content from history/prompt when the model cannot handle it.
-
Poison turn loop: pruneProcessedHistoryImages() only prunes images from turns before the last assistant message. If the image turn caused a failure (no assistant reply saved), it remains after the last assistant turn and is never pruned — creating a permanent failure loop.
Expected Behavior
- Image blocks should be stripped from the transcript context when the model does not support vision (
input does not include "image")
- Alternatively, failed turns containing images should be prunable even without a subsequent assistant reply
Reproduction
- Configure a model provider that does not support vision (e.g.
github-copilot/claude-opus-4.6)
- Do not configure
imageModel fallback
- Upload/paste an image in webchat
- Observe HTTP 400 on every subsequent message until
/new
Affected Code
src/agents/pi-embedded-runner/run/history-image-prune.ts — prune logic only covers already-answered turns
src/agents/pi-embedded-runner/run/attempt.ts:334 — modelHasVision is computed but not used to strip images from context
Bug
When an image enters the session transcript (webchat upload, tool result, etc.) and the model provider does not support vision, the session enters an unrecoverable error loop:
pruneProcessedHistoryImages()only strips images from turns before the last assistant reply — since no assistant reply was saved, the image turn is never pruned/newor/resetRoot Cause
Two issues:
No vision-gating on transcript images: Even when
modelHasVisionisfalse(model resolves withinput: ["text"]), image blocks in the transcript are still sent to the provider. There is no step that strips image content from history/prompt when the model cannot handle it.Poison turn loop:
pruneProcessedHistoryImages()only prunes images from turns before the last assistant message. If the image turn caused a failure (no assistant reply saved), it remains after the last assistant turn and is never pruned — creating a permanent failure loop.Expected Behavior
inputdoes not include"image")Reproduction
github-copilot/claude-opus-4.6)imageModelfallback/newAffected Code
src/agents/pi-embedded-runner/run/history-image-prune.ts— prune logic only covers already-answered turnssrc/agents/pi-embedded-runner/run/attempt.ts:334—modelHasVisionis computed but not used to strip images from context