Multiple sidebar bugs after workspace directory migration: "56 years ago" timestamps, missing threads, threads vanish on click (macOS) #17317
Description
After migrating my workspace from a path containing Chinese characters to an all-English path, the Codex Desktop app exhibits three persistent bugs. The underlying data in state_5.sqlite is fully intact and correct — these are rendering/UI layer issues.
Platform: macOS Darwin 25.4.0 arm64, CLI 0.117.0-alpha.12
Bug 1: All threads display "56 年" (56 years ago) timestamp after restart
After app restart, ALL threads — including newly created ones — show "56 年" (56 years ago) as the relative timestamp. New threads display the correct time at creation, but revert to "56 年" after restart.
This is a Unix epoch (1970) display: 2026 − 1970 = 56 years.
The data is correct — state_5.sqlite timestamps are valid millisecond integers (e.g. 1775804549416 = 2026-04-10), and session_index.jsonl has correct ISO8601 timestamps. The bug is in the app's time rendering on restart.
Bug 2: Some workspaces show "无线程" (no threads) despite having data
The sidebar shows "无线程" for several workspaces, but sqlite has many threads for those exact CWDs:
| Workspace | Threads in sqlite (archived=0) | Sidebar shows |
|---|---|---|
| bilibili-video-analysis | 14 | 无线程 |
| health | 2 | 无线程 |
| drafts | 30 | Only 2 visible |
| work-management | 34 | Partial |
This appears to be the same truncation/pagination bug reported in #14370.
Bug 3: Threads disappear when clicked
Clicking on a thread in the sidebar causes it to vanish from the list. The thread data still exists in sqlite but is no longer rendered.
Additional: codex app-server continuously modifies sqlite
The codex app-server process (running via Cursor extension) continuously un-archives child threads that have been archived, undoing manual state corrections. It un-archives ~51 child threads within seconds.
Steps to reproduce
- Have a workspace with ~247 threads across multiple workspace roots
- Restart Codex Desktop app
- Observe: all timestamps show "56 年" instead of actual relative time
- Observe: some workspace folders show "无线程" despite having threads in sqlite
- Click on any thread → it may disappear from the sidebar
Expected behavior
- Timestamps should display correct relative time (e.g. "3 days ago")
- All workspace folders should list their threads matching sqlite data
- Clicking a thread should open it, not hide it
Environment details
- 247 total threads in
state_5.sqlite - 141
thread_spawn_edges(parent-child relationships intact) - All 247
rollout_pathentries point to existing files on disk - All timestamps in DB are valid millisecond Unix timestamps
- WAL has been checkpointed (WAL file is 0 bytes)
Related issues
- Codex Desktop hides existing workspace threads on macOS #14370 — very similar sidebar truncation behavior (threads hidden despite existing in sqlite)
- Lost part of thread history and all subagent thread history after Codex App restart. #16599 — thread history loss after restart, related WAL/persistence issue
- Durably flush shutdown state #16989 — PR "Durably flush shutdown state" — partial fix that doesn't fully resolve these
Activity
github-actions commentedon Apr 10, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Aley3567 commentedon Aug 16, 2026
Confirmed independently on macOS with ChatGPT/Codex Desktop
26.810.52044 (6662). This appears to be a mixed timestamp-unit bug and is not specific to a workspace-path migration.Evidence
The thread data exposed to the Desktop renderer contains mixed units:
updatedAt: 1786849794(Unix seconds);1783825615000.Passing the first value directly to JavaScript reproduces the symptom:
In the bundled renderer (
webview/assets/app-initial-BqZ9AFkF.js) I found two relevant direct constructions:new Date(q).toISOString()in the hover-card path;new Date(f).toISOString()in the sidebar-row path.The same bundle already contains a timestamp normalizer (minified as
K8c) that multiplies second-scale values by 1000, but these two paths bypass it. The installed application was not modified; its signature still verifies.Suggested fix
The durable fix should normalize timestamps once at the thread DTO boundary, rather than teaching every component about seconds vs. milliseconds:
Then keep the renderer's internal contract as epoch milliseconds (or
Date) only.For a minimal hotfix, route both direct call sites through the existing normalizer:
Regression coverage should include integer seconds, fractional seconds, milliseconds, missing/invalid values, hover cards, and sidebar rows. That would fix the displayed age without rewriting any persisted timestamps.
Aley3567 commentedon Aug 17, 2026
Follow-up: the timestamp bug reproduced again in ChatGPT/Codex Desktop
26.810.52044 (6662).I validated the minimal renderer hotfix locally by routing the two bypassing call sites through the bundle's existing seconds/milliseconds normalizer:
Verification results:
8779before and after);This confirms that timestamp-unit normalization is sufficient for these two UI paths. The local patch is only a diagnostic/workaround: an app update or repair can replace
app.asar, so the durable upstream fix should still normalizeupdatedAtonce at the thread DTO boundary and expose a milliseconds-only internal contract. Component-level normalization is useful as defense in depth, but should not be the primary contract.