The symptom looked like lost work
I hit a nasty local-first bug after moving and renaming a long-running Codex workspace folder. When I restarted the app, it looked like a pile of important threads had disappeared.
In the thread list UI, it showed up like a brand-new workspace with no history.
What I found in local state
The threads were still present on disk. The failure was identity drift: one workspace had split into two identities because the old root path survived in multiple local stores.
One part of the app trusted the new path. Another store still treated the old path as canonical. On startup, stale references kept winning and rebuilding the wrong identity.
Why a quick alias was not enough
I tried the compatibility route first. If the old path stayed reachable, maybe the app would reconnect cleanly.
A symlink helped with reachability, but the identity conflict survived. Once stores disagree on the canonical root, aliasing only hides the drift.
Why this was confusing in practice
Codex inspection kept reporting that internal state looked right and repeatedly suggested restart. From the machine side, each store looked valid in isolation.
From the human side, the Electron thread queue kept coming back empty for that workspace after each restart. So the UI reality and the internal check reality were out of sync.
What actually fixed it
Codex backend repairs were necessary and technically correct:
- session metadata normalized
- thread database rows normalized
- global workspace-state metadata normalized
But that alone did not make the app stable. The sequence that held was: fully quit Codex, run the terminal repair step, then reopen Codex cleanly.
That stopped startup from overwriting state and finally attached the thread history back to one identity.
The practical move that mattered most was treating this as one migration sequence instead of isolated edits. Each store can look correct on its own, but startup precedence can still resurrect stale identity unless everything is aligned and reloaded in order.
The lesson for local-first tools
Workspace rename should be implemented as identity migration. If it is handled as path text replacement, ghost workspaces and duplicate thread histories are likely once the app has real persistence behind it.
This is not a Codex-only problem. Any desktop client with multi-store persisted state can hit the same failure mode.
There is also a user-side lesson here. A lot of us using Codex are not app developers, so trying to fix app identity state from the outside is a first-time experience.
It was frustrating, but it was also a real learning moment. Problem solving got harder when Codex kept telling me to reload without visually inspecting what I could already see in the thread queue. That gap between internal checks and visible UI state is where the real diagnosis had to happen.
What robust rename handling should include
A robust implementation should promote one canonical workspace identity above all path aliases, migrate persisted root references transactionally, and explicitly test stale-path resurrection during startup.
Compatibility aliases are still useful, but as a bridge only. They should support migration windows and rollback safety, not function as the repair for split identity state.
My takeaway
I wanted to write this down because it is easy to misdiagnose under pressure. The visible failure looked like disappearing work, while the underlying issue was identity drift across persistence layers.
There was a direct cost to getting this wrong. Every minute I spent trying to let Codex solve its own problem burned tokens and took time away from my actual work.
I expect this class of issue to show up more as agent tooling gets more local and stateful. Strong tooling will treat rename as migration with explicit invariants, startup checks, and repair-safe rollback points.
Source trail: this came from a same-day incident summary thread on April 13, 2026.
Related context: systems outcomes: what actually changed when I started pairing with agents.