Skip to content

macOS Codex app: restored thread is idle but paginated history persists final turn as inProgress #40563

Open

Description

@mr-ryan-james

What version of the Codex App are you using (From “About Codex” dialog)?

26.818.61809 (build 7019)

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.5.0 arm64 arm

What issue are you seeing?

Summary

One long-running local conversation in the macOS Codex desktop app became stuck after a sampling stream disconnected during its final follow-up turn. The durable transcript and SQLite databases passed integrity checks, but the final turn remained persisted as inProgress with no terminal metadata. The bundled app-server later reconstructed that historical turn as interrupted and restored the thread runtime as idle; the disconnection is an observed precursor, not a proven root cause.

This left three lifecycle views in disagreement:

paginated history projection: turn = inProgress
app-server reconstructed history: turn = interrupted
app-server live thread runtime: thread = idle, canAcceptDirectInput = true

The Desktop UI behaved as if the conversation were still incomplete: it loaded inconsistently and could not reliably resume the conversation through its normal UI, despite the later app-server runtime reporting an idle, input-capable thread.

Sanitized observed sequence

  1. A long local Desktop conversation had completed earlier tool and child-worker activity.

  2. During a final follow-up turn, the sampling stream disconnected. The local log recorded:

    stream disconnected - retrying sampling request ... sampling_error=stream disconnected before completion: failed to send websocket request: Connection closed normally
    
  3. The turn continued far enough for later reasoning/tool events and a final successful command result to be persisted.

  4. No final assistant message, task_complete, turn_aborted, or other terminal turn event was found in the persisted rollout after the last result.

  5. After reopening the thread, Desktop did not reconcile the orphaned turn into a recoverable terminal state.

The final row in the paginated history projection remained:

status                  = inProgress
started_at              = set
completed_at            = NULL
duration_ms             = NULL
final_agent_item_id     = NULL
rollout_end_ordinal     = NULL
rollout_end_byte_offset = NULL
error_json              = NULL

After recovery through the bundled app-server, thread/read with includeTurns=true reconstructed the turn as interrupted, and thread/resume reported the thread as idle and able to accept input. However, the persisted history row still remained inProgress with the terminal fields above unset.

What steps can reproduce the bug?

This was observed in one real local thread; I do not yet have a deterministic public reproducer. The conditions observed in this incident were:

  1. A long-running local conversation was open in Codex Desktop on macOS, and the app's paginated-history projection was present.
  2. A turn persisted normal events and a completed tool result.
  3. The model stream had disconnected earlier in the turn, and no terminal turn event was persisted after the last result.
  4. Desktop was fully quit and reopened, then the conversation was opened again.
  5. In the observed incident, the paginated history projection retained inProgress even though thread/read reconstructed the turn as interrupted and the resumed runtime had no active turn.

The affected conversation was also archived during an attempted recovery step; this was not the initial trigger. Using thread/unarchive restored the thread to the active list but did not reconcile the stale inProgress history row.

No session/thread identifier, prompt, project content, local path, or artifact name is included because this is a public issue.

What is the expected behavior?

When Desktop starts, reads, resumes, or unarchives a thread, an orphaned inProgress turn with no live request/stream owner should be reconciled atomically to a recoverable terminal state such as interrupted or failed.

In particular:

  • reconstructed turn history, the paginated history projection, aggregate thread state, and Desktop UI should agree;
  • terminal timestamps/end offsets should be finalized consistently;
  • archive/unarchive and resume should not leave stale lifecycle fields in the history projection;
  • the composer should become usable when the runtime is actually idle; and
  • if automatic reconciliation is unsafe, Desktop should expose a clear user-visible Recover/Retry/Continue action instead of leaving the conversation stuck.

Additional information

Integrity checks

Before attempting recovery, I made a backup and performed read-only checks:

  • the rollout contained thousands of valid JSONL records and was internally well-formed;
  • every line parsed, the file ended with a newline, and there were no NUL bytes;
  • the stored projection offset matched the exact rollout EOF;
  • every persisted history item contained valid JSON;
  • SQLite PRAGMA quick_check returned ok for the state, paginated history, logs, goals, memories, and queue databases;
  • related child threads had completed normally; and
  • there was no live writer for the old thread and no relevant database-corruption or crash indication.

These checks found no evidence of malformed rollout JSONL or general SQLite corruption; the observed state is consistent with a lifecycle/projection reconciliation failure.

Manual recovery performed

I did not manually edit SQLite or delete the conversation. After backing up the affected rollout and local state files, I used the app-server bundled with the macOS app over stdio:

  1. initialize / initialized
  2. thread/unarchive
  3. thread/read with includeTurns=true
  4. thread/resume
  5. thread/unsubscribe, then a clean server exit

The documented app-server protocol calls moved the rollout back to the active sessions location, cleared the archived metadata, reconstructed the last turn as interrupted, and restored an idle/resumable runtime. This made the conversation usable again. The stale history-projection row nevertheless remained inProgress, so the persisted inconsistency was not actually repaired.

The inProgress projection row was observed before the diagnostic app-server calls and remained unchanged afterward; those calls did not create the inconsistency. Affected session runtime metadata recorded 0.149.0-alpha.4.1; the bundled recovery app-server reported 0.149.0-alpha.4.3. App-server protocol reference: https://learn.chatgpt.com/docs/app-server

Related reports and distinction

Privacy

Project subject matter, prompts, working-directory paths, filenames, artifacts, conversation identifiers, account details, and raw logs have been intentionally omitted. I can provide a narrower sanitized lifecycle trace privately if maintainers identify a secure channel and the specific fields needed.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Aug 25, 2026
  2. github-actions commented on Aug 25, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

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 appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingsessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions