In-process app-server drops AgentMessageDelta under backpressure, truncating TUI output

Open 💬 2 comments Opened Jul 18, 2026 by sky-bro

What version of Codex CLI is running?

codex-cli 0.144.5

Which model were you using?

gpt-5.6-sol through a custom Responses HTTP provider (supports_websockets = false). The provider does not appear relevant: the complete response was persisted before the TUI transport loss.

What platform is your computer?

Linux xyz 6.18.12-1-MANJARO x86_64 GNU/Linux

Terminal multiplexer: tmux 3.6a

What issue are you seeing?

The interactive CLI TUI can render a truncated assistant answer when its in-process app-server notification queue is full.

In one occurrence, the API response and rollout contained the complete ending:

````markdown
设置后,后续请求会带:

"reasoning": {
  "effort": "low",
  "summary": "detailed",
  "context": "all_turns"
}

````

but the live terminal ended at:

设置后,后续请求 "

The persisted rollout contained the complete assistant response_item and task_complete.last_agent_message, so this is not model/API truncation. The complete HTTP Responses stream was also independently captured. The TUI consolidation log recorded a shorter source (source_len=1902, versus 2008 bytes in the complete persisted answer).

At the same timestamp, logs_2.sqlite contained repeated warnings:

dropping in-process server notification (queue full)
dropping in-process app-server event because consumer queue is full
app-server event consumer lagged

This initially looked like fenced-JSON Markdown corruption, but the JSON block merely occurred after the missing transcript delta.

Deterministic source-level reproduction

Current main at 56395bddaf26eb2829387ca6a417bf9128e5b239 still has inconsistent must-deliver classification between the two in-process queue layers.

Add this test to codex-rs/app-server/src/in_process.rs:

use codex_app_server_protocol::AgentMessageDeltaNotification;

#[test]
fn guaranteed_delivery_helpers_cover_agent_message_deltas() {
    assert!(server_notification_requires_delivery(
        &ServerNotification::AgentMessageDelta(AgentMessageDeltaNotification {
            thread_id: "thread-1".to_string(),
            turn_id: "turn-1".to_string(),
            item_id: "item-1".to_string(),
            delta: "```json\n{\"reasoning\": true}\n```".to_string(),
        })
    ));
}

Then run:

cd codex-rs
cargo test -p codex-app-server guaranteed_delivery_helpers_cover_agent_message_deltas --lib -- --exact

The assertion fails deterministically because codex-rs/app-server/src/in_process.rs::server_notification_requires_delivery currently matches only:

TurnCompleted
ThreadSettingsUpdated
ExternalAgentConfigImportCompleted

As a result, AgentMessageDelta reaches the event_tx.try_send(...) branch and is dropped when that queue is full.

By contrast, codex-rs/app-server-client/src/lib.rs::server_notification_requires_delivery correctly treats the following as lossless and forwards them with send(...).await:

ItemCompleted
AgentMessageDelta
PlanDelta
ReasoningSummaryTextDelta
ReasoningTextDelta

The second layer therefore cannot preserve a transcript delta that the first layer has already dropped.

Expected behavior

Assistant, plan, and reasoning transcript deltas and authoritative item/turn completion notifications should never be dropped under in-process backpressure. The TUI should render the same assistant message that is persisted in the rollout.

Both in-process queue layers should share the same must-deliver classification, or the app-server layer should include all transcript and completion notification variants and use send(...).await for them.

Additional information

Related reports:

  • #20777 reported the same dropping in-process server notification (queue full) warning and was closed as a duplicate of #20601.
  • When closing #20601, maintainers asked users to file a new report if similar symptoms recurred.
  • PR #21870 addressed TUI active-thread routing, but its changed files were limited to codex-rs/tui; it did not align the lower-level helper in codex-rs/app-server/src/in_process.rs.
  • A comment on #20601 explicitly proposed aligning the lower-level helper for ItemCompleted and assistant/plan/reasoning deltas, which matches the remaining gap in current main.

No raw rollout or SQLite database is attached because they contain private prompts and local paths. A sanitized thread/session identifier can be provided privately or through /feedback if useful.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗