openai / openai/codex

[macOS Desktop] Active Goal loses persisted row, becomes unmanageable, and rewrites local rollout path to /root

Open
#40,195 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Summary

After updating Codex Desktop and running an active Goal on an existing local macOS thread, the Goal completed one long turn but did not continue. The persisted Goal row disappeared while the turn was still running, while the Desktop UI continued to treat the Goal as active.

This produced a split-brain state:

  • Goal auto-continuation failed with goal_not_found.
  • Pause, cancel, and clear controls could not manage the Goal.
  • After force-quitting and reopening the app, the same local thread could not be restored because its state_5.sqlite.threads.rollout_path had been rewritten to a Linux /root/.codex/... path.
  • The actual macOS rollout JSONL still existed and was valid.

Manual SQLite repair was required to reopen the thread.

Environment

  • macOS 26.5 (25F71), arm64
  • ChatGPT/Codex Desktop 26.818.41509, build 6962
  • CLI version recorded by the affected thread: codex-cli 0.148.0-alpha.15
  • Current bundled CLI after restart: codex-cli 0.149.0-alpha.4.1
  • Model: gpt-5.6-sol
  • Thread type: local macOS Desktop thread, not Cloud or Remote
  • Time zone: UTC+8

Observed timeline

All times below are local UTC+8.

  1. 02:23: Goal creation succeeded.
  2. 02:2304:05: one long Goal turn ran for approximately 1 hour 42 minutes.
  3. Around 03:54: goals_1.sqlite was recreated as a valid but empty database. The preserved prior Goal database did not have a valid SQLite header.
  4. 04:05: the turn completed. Automatic continuation immediately failed because the backend no longer had a Goal row.
  5. The Desktop UI still presented the Goal as active. Pause, cancel, and clear did not restore consistency.
  6. Around 12:00: the app was force-quit because the Goal could not be controlled.
  7. After restart, opening the thread failed because the local rollout path in state_5.sqlite pointed to /root/.codex/... instead of the existing macOS path.

The Goal persistence failure therefore happened several hours before the force-quit. The force-quit exposed the invalid rollout path but did not cause the original Goal row loss.

Errors

At automatic Goal continuation:

cannot update goal for thread ...: no goal exists
failureReason=goal_not_found
Failed to continue active thread goal

After trying to pause/clear the Goal:

thread/goal/set: no goal exists
thread/goal/clear: success, but the UI still treated the Goal as active

After restarting Desktop:

failed to resolve rollout path
`/root/.codex/sessions/.../rollout-....jsonl`:
file does not exist

Local evidence

  • The supposedly missing transcript existed under /Users/<redacted>/.codex/sessions/....
  • It was 480,201,360 bytes with 34,991 newline-delimited JSON records and passed a full JSON parse.
  • The thread row still had a macOS working directory under /Users/<redacted>/... and was classified as local, but its rollout_path used /root/.codex/....
  • A second local thread had the same /root rollout-path corruption.
  • The active goals_1.sqlite.thread_goals table was empty after the failure.
  • logs_2.sqlite also reported database disk image is malformed, with freelist/pointer-map corruption. 250,333 of 268,648 pages (93.18%) were on the freelist. Recovering reachable records produced a healthy database of about 60 MiB.
  • The conversation transcript itself was not corrupt or missing.

No full transcript, database, username, repository path, credentials, or conversation content is included in this public report.

Reproduction sequence

This is the observed sequence; I do not yet have a deterministic minimal reproducer for the database migration timing.

  1. Update Codex Desktop.
  2. Open an existing local macOS thread.
  3. Start a Goal and let it run through a long turn.
  4. Allow the active Goal to cross a Desktop/app-server storage migration or process transition.
  5. At turn completion, observe whether automatic continuation reports no goal exists while the UI still shows an active Goal.
  6. Try pause, cancel, and clear.
  7. Restart Desktop and reopen the thread.
  8. Inspect whether the local threads.rollout_path was normalized to /root/.codex/... even though the rollout exists under the macOS home directory.

Expected behavior

  • Goal persistence should be atomic with active Goal execution and storage migration.
  • UI Goal state should reconcile when the persisted Goal row is missing or reset.
  • Pause, cancel, and clear should return an actionable state instead of leaving a zombie Goal.
  • A local macOS thread must never receive a Linux /root/.codex/... rollout path.
  • Startup should detect and repair host/path mismatches when the canonical rollout exists.
  • SQLite recovery should not silently replace a damaged Goal database with an empty database while the UI continues to advertise an active Goal.

Impact

  • Long-running Goal execution stops without completing the objective.
  • The Goal cannot be paused, cancelled, or cleared.
  • Existing local chats become inaccessible.
  • Users may believe transcript data was deleted even though only metadata is wrong.
  • Manual database backup, path repair, and log-database recovery are required.

Related issues

  • #23984 — older Goal DB/schema/process mismatch; closed as completed, but this appears to be a regression/different active-migration failure.
  • #24423 — Goal operations fail around older rollout compatibility, but the current case loses an already-active Goal after a successful long turn.
  • #31074 — stale rollout paths where backing files are genuinely missing; here the rollout exists and the stored path points to the wrong operating-system home.
  • #40178 — restart/runtime transition can desynchronize durable history and the UI; adjacent but not the same Goal-store and host-path failure.
  • #28224 — historical logs_2.sqlite write amplification; the current case additionally had structural freelist/pointer-map corruption.

Please investigate:

  1. Atomicity of Goal-store migration/recovery while a Goal turn is active.
  2. Reconciliation between frontend active-Goal state and goals_1.sqlite.
  3. Host-aware normalization of local rollout paths.
  4. Startup self-healing when the indexed rollout path is wrong but the canonical JSONL exists.
  5. Automatic detection and safe reconstruction of corrupted local SQLite stores.

Sanitized timestamps and targeted log excerpts can be provided if needed.

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 by inspecting the goals_1.sqlite, state_5.sqlite, and logs_2.sqlite migration/recovery paths, including thread_goals and threads.rollout_path. Run the documented update, long-running Goal, restart, and thread-reopen sequence, then compare persistence and UI reconciliation at each transition. Done means active Goals remain manageable, local macOS paths stay host-correct, and damaged stores are detected and safely recovered.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
databases, desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.