Skip to content

[Windows] final_answer persists without task_complete, composer remains in Insert mode #40552

Open

Description

@tao943

Codex Desktop turn remains active after final_answer, so the composer only offers Insert

Summary

In a long-running Codex Desktop task, the assistant's final answer is rendered, but the turn sometimes remains active. The composer therefore continues to show the Insert/steer behavior instead of allowing a normal next message.

This is confusing because the visible assistant response has already ended and may itself contain a small follow-up question, but the user cannot answer it as a new turn.

Environment

  • Codex Desktop package: OpenAI.Codex_26.818.8289.0_x64
  • OS: Windows 10.0.26200.0
  • PowerShell: 7.6.4
  • Task type: local desktop task backed by a Git repository
  • Task history: very long; multiple earlier compactions/continuations
  • No app terminal session was attached to the task at diagnosis time

Observed behavior

  1. The assistant performs several tool calls.
  2. Some network-backed commands yield without completing and are later explicitly terminated.
  3. The assistant emits a visible final_answer containing a short clarification question.
  4. The UI still shows the task as working.
  5. The composer only permits Insert/steer instead of starting a normal user turn.
  6. The task eventually has to be interrupted/aborted before normal interaction resumes.

Expected behavior

Once a final_answer has been persisted and all tool calls have terminal results, the turn should emit task_complete, transition the task to idle, and restore the normal send behavior.

If the backend is still doing required post-processing, the UI should distinguish that state from model/tool execution and should not leave a visible clarification question that the user cannot answer normally.

Sanitized event evidence

The local JSONL event stream showed the following ordering (timestamps are local log timestamps; message contents and tool arguments are omitted):

04:52:02  custom_tool_call exec -> completed
04:52:53  function_call wait
04:53:14  function_call_output
04:53:22  function_call wait
04:53:43  function_call_output
04:53:48  function_call wait (terminate)
04:53:48  function_call_output
04:53:57  custom_tool_call exec -> completed
04:54:36  function_call wait (terminate)
04:54:37  function_call_output
04:54:47  custom_tool_call exec -> completed
04:55:25  function_call wait (terminate)
04:55:25  function_call_output
04:55:45  agent_message phase=final_answer
04:55:45  response_item message role=assistant phase=final_answer
04:55:45  token_count
            [no task_complete event]
04:57:33  response_item message role=developer
04:59:03  turn_aborted

The important invariant violation is final_answer without a subsequent task_complete, even though every visible tool call had a terminal output and no curl or gh child process remained.

Frequency

Intermittent, but repeatedly noticed in this specific long task. Shorter tasks reportedly do not exhibit the same behavior as often.

Ranked hypotheses

  1. A terminated yielded tool cell produces a terminal tool output but leaves the turn orchestration state waiting for another completion signal.
  2. A late dynamic developer/context refresh races with final-answer completion and prevents task_complete from being emitted.
  3. Long-thread compaction or persistence delays expose the race more frequently.
  4. Less likely: the backend turn is already complete but the composer fails to refresh. The captured event stream argues against this because task_complete itself is absent.

Suggested regression coverage

Add an integration test for this lifecycle:

start turn
-> tool call yields a running cell
-> terminate/wait returns terminal output
-> assistant emits final_answer
-> dynamic context/developer update arrives near finalization
-> assert exactly one terminal turn event
-> assert task status becomes idle
-> assert composer accepts a normal user message

Also assert that every persisted final_answer is followed by either task_complete or an explicit terminal error/abort within a bounded time.

Workaround

  • Avoid launching additional network probes after enough evidence is available.
  • Explicitly terminate every yielded tool cell and confirm no child process remains.
  • If the final answer is visible but the composer still shows Insert, stop the current turn or open a fresh/forked task.
  • For clarification-only exchanges, avoid tool calls so the turn has fewer lifecycle edges.

Privacy

This report intentionally excludes user prompts, project paths, API keys, tool arguments, model reasoning, and task identifiers. The full local event trace can be supplied privately if requested.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    tool-callsIssues related to tool calling
    on Aug 25, 2026
  2. github-actions commented on Aug 25, 2026

    @github-actions
    Contributor
  3. tao943 commented on Aug 25, 2026

    @tao943
    Author

    Thanks. I reviewed #39988 and #39572. This report appears related at the turn-lifecycle layer, but the observed failure point is different.

    In both suggested issues, the turn stalls before producing a final answer. In #40552, the final_answer was already rendered and persisted, and every visible tool call had a terminal output, but no task_complete followed. The composer therefore remained in Insert/steer mode until the turn was aborted.

    The captured ordering was:

    tool calls -> terminal outputs
    -> agent_message phase=final_answer
    -> response_item phase=final_answer
    -> token_count
    -> [no task_complete]
    -> later developer/context event
    -> turn_aborted
    

    No residual curl.exe or gh.exe child process remained when this was diagnosed. This may therefore be a finalization-state race after a persisted final answer, rather than a model-stream stall before completion.

  4. ZiggyKor commented on Sep 13, 2026

    @ZiggyKor

    Additional sanitized Windows evidence observed on 2026-09-13, consistent with this report's finalization symptom (not a proven identical root cause).

    • Desktop log version: 26.908.40834.
    • The affected long-lived session's stored cli_version is 0.148.0-alpha.9; this is session metadata, not proof of the currently loaded app-server binary. The separately resolved CLI used for diagnostics is 0.154.0-alpha.6.2.
    • A fully rendered final reply is persisted as an agentMessage with phase=final_answer.
    • In thread_history_1.sqlite, that same turn still has status=inProgress, completed_at=NULL, and a non-null final_agent_item_id referencing that final reply.
    • The three most recent tool-call items preceding the final reply are all status=completed. This bounded check is not an assertion that every historical call has been audited.
    • The inspected rollout tail contains the affected task_started and subsequent user turns, but no matching task_complete for that affected turn.
    • An earlier affected turn had a persisted final reply and later needed manual cancellation; its log reported that the task did not complete gracefully after 100ms.

    The same conversation's logs contain stream disconnections, request timeouts, and HTTP fallback. A separate official codex doctor run outside the command sandbox found configured authentication, healthy databases and successful desktop app-server initialization, but a Responses WebSocket timeout and an unreachable desktop update/runtime CDN. These are correlated observations, not proof that networking causes the missing terminal event. It also reported rollout-inventory warnings not yet attributed to the affected conversation.

    No live SQLite rows were edited, no conversation was deleted, and no processes from other tasks were terminated. A deterministic minimal reproducer is not available. Could maintainers investigate final-message/terminal-event ordering and recovery of an orphaned history row, rather than only whether external commands exited?

    This comment intentionally omits conversation/turn IDs, local paths, research content, account information and raw logs. Those details have not been uploaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingsessionIssues involving session (thread) management, resuming, forking, naming, archivingtool-callsIssues related to tool callingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions