view_image rejection on text-only models poisons model output — all subsequent turns return last_agent_message: null
Bug: view_image rejection on text-only models poisons model output — all subsequent turns return last_agent_message: null
Summary
When a text-only custom model (e.g. glm-5.2:cloud via Ollama provider) calls view_image, Codex rejects the call with "view_image is not allowed because you do not support image inputs". This rejection, fed back as a function_call_output, corrupts the model's output format: from that point onward, the model routes ALL output through the reasoning channel and never produces a message/assistant item. Every subsequent turn completes with last_agent_message: null — the UI shows nothing. The pattern is self-reinforcing: reasoning-only conversation history perpetuates reasoning-only output.
Environment
- Codex Desktop (macOS), build
26.707.31428 - Model:
glm-5.2:cloudvia built-inollamaprovider (Responses API) - Model catalog:
input_modalities: ["text"]only — no image support - Config:
model_reasoning_effort = "medium",model_reasoning_summary = "detailed" - OS: macOS 15, Apple Silicon
Reproduction
- Start a Codex Desktop session with a text-only model (e.g.
glm-5.2:cloudvia Ollama). - Work on a task where the model decides to view an image (e.g. macOS menubar app development — model takes a screenshot and calls
view_imageto inspect it). - The model calls
view_imagewith a path to a PNG. - Codex returns:
function_call_output: "view_image is not allowed because you do not support image inputs" - The model continues working (more tool calls, reasoning), but on the final step of the turn, it produces only a
reasoningresponse item — nomessage/assistantitem. task_completefires withlast_agent_message: null. UI shows nothing.- All subsequent turns (even trivial ones like "selam") produce only reasoning items and complete with
last_agent_message: null.
Root cause analysis (from rollout JSONL)
Two sessions were compared — same model, same config, different outcomes:
| Metric | Healthy session | Broken session |
|--------|----------------|----------------|
| Session ID | 019f4c0b-... | 019f4c7f-... |
| Model | glm-5.2:cloud | glm-5.2:cloud |
| Provider | ollama | ollama |
| reasoning_effort | medium | medium |
| reasoning_summary | detailed | detailed |
| Turns | 52 (all OK) | 32 (last 5 NULL) |
| Max per-request context | 350,764 tokens | 261,648 tokens |
| Total cumulative tokens | 107M | 31M |
| view_image calls | 0 | 1 (rejected) |
| NULL last_agent_message | 0 | 5 |
The healthy session reached higher context usage (350K per-request, 107M total) with zero issues. The broken session broke at lower context usage (261K per-request, 31M total). Context window is definitively not the cause.
Trigger event (broken session, turn 27):
[line 1206] response_item/function_call: view_image, args={"path":"/tmp/menubar.png"}
[line 1207] response_item/function_call_output: "view_image is not allowed because you do not support image inputs"
[line 1208] tokens: last_out=16 (only 16 output tokens — model barely responded)
After this rejection, the turn continued with 9 function calls and 6 reasoning items. On the final step, the model produced a reasoning item (id: rs_17161) with the full response in summary and encrypted_content, but content: null — and no separate message/assistant item.
Turn-by-turn comparison (response item counts):
| Turn | Reasoning items | Assistant messages | last_agent_message |
|------|---------------|-------------------|---------------------|
| 26 (last working) | 0 | 1 | OK |
| 27 (trigger) | 6 | 0 | NULL |
| 28 | 1 | 0 | NULL |
| 29 | 1 | 0 | NULL |
| 30 | 1 | 0 | NULL |
| 31 | 1 | 0 | NULL |
Reasoning item structure is identical in working and broken turns (content: null, summary with text, encrypted_content with text). The difference is that working turns ALSO produce a separate message/assistant item; broken turns do not.
From turn 28 onward, the model produces only a single reasoning item per turn (no tool calls, no assistant message) and immediately completes with last_agent_message: null. The conversation history now contains reasoning-only outputs (no assistant messages), and the model perpetuates this pattern.
Expected behavior
view_imageshould not be exposed to text-only models at all. The tool list should be filtered based oninput_modalities— if a model only supports["text"],view_imageshould not appear in the available tools. This prevents the model from ever calling it.
- If a tool rejection must occur at call time (e.g. as a fallback), the rejection response should be handled in a way that does not corrupt the model's output format. The current behavior — where a single rejected tool call permanently breaks assistant message generation for the entire session — is a severe regression.
Suggested fix
Primary: Filter view_image (and any other image-dependent tools) from the tool list when the active model's input_modalities does not include "image". This is the cleanest fix — the model can never call a tool it can't use.
Secondary: Investigate why a function_call_output containing an error message causes the model to permanently switch from content output to reasoning-only output. This may be an Ollama Responses API adapter issue where error-type tool outputs are not properly handled in the response stream, causing the model's content tokens to be misrouted to the reasoning channel.
Impact
- Severity: High — the entire session becomes unusable (no responses shown to user) after a single
view_imagecall on a text-only model. - Recovery: Only by starting a new session. The broken session cannot recover — every turn produces reasoning-only output.
- Affected models: Any text-only model accessed via the Ollama provider (glm-5.2:cloud, kimi-k2.6:cloud, qwen3.5:cloud, etc.) — all have
input_modalities: ["text"]. - Trigger likelihood: Medium — the model must decide to call
view_image, which happens when working on visual verification tasks (UI screenshots, menubar apps, etc.).
Session data
- Broken session rollout:
~/.codex/sessions/2026/07/10/rollout-2026-07-10T17-47-41-019f4c7f-a632-7a42-86c7-24ed395e8067.jsonl(1268 lines) - Healthy session rollout:
~/.codex/sessions/2026/07/10/rollout-2026-07-10T15-41-04-019f4c0b-b820-7cc0-ab65-3a30595fb55f.jsonl(2513 lines) - Model catalog:
~/.codex/ollama-launch-models.json - Config:
~/.codex/config.toml