openai / openai/codex

Codex Desktop: background turn reported completed/interrupted while JSONL continues without final_answer or task_complete

Open
#38,972 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

Codex Desktop/app-server can report a background-created turn as completed/interrupted while the underlying rollout JSONL is still receiving events and has no final_answer or task_complete.

This appears to affect threads created through app-server thread/start + turn/start, where the external orchestrator only receives acceptance, not final completion.

Environment

  • Codex Desktop release observed in logs: 26.810.41047
  • app-server version observed in logs: 0.148.0-alpha.9
  • session cli_version: 0.146.0
  • Host: local macOS
  • Model provider: codex_local_access
  • Timezone used below: Asia/Shanghai, UTC+8

Evidence

Example B, no compaction/handoff case:

  • Thread: 01a00ee4-6014-7632-ae22-0aef4775476d
  • Turn: 01a00ee4-68c7-7492-9f8f-31fcd00750ae
  • Local JSONL: $HOME/.codex/sessions/2026/08/17/rollout-2026-08-17T16-44-02-01a00ee4-6014-7632-ae22-0aef4775476d.jsonl
  • At 2026-08-17 16:52:07 UTC+8, the JSONL had 224 lines, latest event timestamp 2026-08-17T08:52:07.812Z.
  • The JSONL contained no final_answer and no task_complete.
  • read_thread returned the turn as status="interrupted", error=null, completedAt=null.
  • wait_threads(timeoutMs=0/5000) woke with reason="turnCompleted", but the same response still had latestTurn.status="interrupted" and completedAt=null.
  • During polling, the JSONL kept growing, e.g. 206 -> 216 -> 224 lines, showing events were still being appended after the turn was treated as completed/interrupted.
  • Desktop log around 2026-08-17T08:46:50.390Z showed maybe_resume_success ... latestTurnStatus=interrupted ... markedStreaming=true; the JSONL continued appending after that.

Example A, compaction/handoff-adjacent case:

  • Thread: 01a00ec3-e645-7822-91db-1257005fd4c4
  • A phase="final_answer" handoff summary appeared mid-turn at 2026-08-17 16:12:41 UTC+8.
  • The actual same-turn task_complete was later at 2026-08-17 16:17:19 UTC+8.
  • Desktop appeared to treat the turn as completed before the real task_complete.

Expected Behavior

  • wait_threads should not wake with reason="turnCompleted" unless the turn has a real terminal state.
  • read_thread and Desktop should not present a turn as completed/interrupted while the same turn is still receiving JSONL events.
  • A mid-turn phase="final_answer" should not be treated as task completion without task_complete.

Actual Behavior

  • wait_threads can wake as turnCompleted while the latest turn is still interrupted with completedAt=null.
  • Desktop/read model can diverge from the underlying rollout JSONL stream.
  • Users see background Codex tasks as if they stopped or completed halfway.

Impact

External orchestrators that create Codex tasks through app-server cannot reliably tell whether a turn genuinely finished. Desktop UI also makes background tasks look like they stopped or completed halfway.

Suspected Area

Codex Desktop/app-server read model or wait semantics for background-created turns. This is not limited to context compaction: compaction/handoff final_answer is one trigger shape, but the second example reproduces without final_answer or task_complete.

Diagnostics Snippets

Minimal excerpts only; full logs/JSONL may contain local paths, prompts, project names, message content, and tool outputs.

wait_threads contradiction
{
  "wake": {
    "reason": "turnCompleted",
    "turnId": "01a00ee4-68c7-7492-9f8f-31fcd00750ae",
    "threadId": "01a00ee4-6014-7632-ae22-0aef4775476d"
  },
  "latestTurn": {
    "id": "01a00ee4-68c7-7492-9f8f-31fcd00750ae",
    "status": "interrupted",
    "error": null,
    "completedAt": null,
    "durationMs": null
  }
}
JSONL terminal-event check
{
  "line_count": 224,
  "last_timestamp": "2026-08-17T08:52:07.812Z",
  "finalLines": [],
  "completeLines": []
}
Desktop resume log summary

At 2026-08-17T08:46:50.390Z, Desktop logged a successful resume for the same thread with:

maybe_resume_success ... latestTurnId=01a00ee4-68c7-7492-9f8f-31fcd00750ae latestTurnStatus=interrupted markedStreaming=true ... turnCount=1

The rollout JSONL continued appending after this log line.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the app-server thread/start and turn/start flow, then inspect read_thread and wait_threads handling of background turns against the rollout JSONL stream. Reproduce the reported contradiction using the supplied thread and turn behavior, including a mid-turn final_answer phase. Done means wait_threads wakes only for a real terminal event and read_thread/Desktop no longer report completion while JSONL continues.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.