You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Thread rename updates session_index but leaves SQLite thread title stale #16405
Renaming a thread updates session_index.jsonl, but it does not update threads.title in state_*.sqlite for the same thread_id.
That leaves a persistent split-brain state between the append-only session index and the SQLite metadata store.
Newer resume/list code paths can paper over this by hydrating thread.name from session_index, but the underlying drift still remains and can break older resume flows, title-based search, or any surface that relies on SQLite title as the source of truth.
Concrete drift observed
For a real saved thread:
session_index.jsonl contained "Provision server VM"
threads.title in SQLite still contained "server vm"
the same thread id was 019c4b73-a91e-7640-9ef6-b1bf18951bb6
User-facing symptom
On affected CLI paths / older builds, codex resume 'Provision server VM' can fail with:
ERROR: No saved session found with ID Provision server VM. Run `codex resume` without an ID to choose from existing sessions.
while the same session is still resumable from the picker.
Even on newer builds where picker/list behavior is corrected by name hydration, the persisted metadata remains inconsistent.
Expected behavior
A thread rename should keep both persistence layers in sync:
append the new name to session_index.jsonl
update threads.title in SQLite for the same thread id
Why this matters
session_index is append-only and currently acts as the latest rename source, but SQLite still powers thread metadata, sorting, and some lookup/search paths. If the two stores diverge, name-based behavior becomes version-dependent and path-dependent.
Proposed fix
When append_thread_name(...) succeeds, perform a best-effort SQLite title sync for the same thread_id.
That keeps existing semantics (session_index remains append-only) while eliminating stale threads.title rows.
Can you provide repro steps? You're describing internal details, but I'd like to understand the user-visible behaviors and the steps needed to repro the problem.
I can reproduce this on Codex Desktop for macOS, and it also has a visible sidebar/user-facing impact when the first prompt is long.
Environment:
Codex Desktop: 26.519.31651, bundle version 3017
bundled / CLI version: codex-cli 0.133.0
macOS: 26.5 build 25F71, x86_64
User-visible symptom:
A thread that starts with a long absolute file path / long task prompt can continue to show that long first prompt as the chat title in the Desktop Projects sidebar, even after a concise generated/renamed title exists elsewhere.
This makes the Projects list hard to scan because real work often starts with paths like /Users/<user>/Desktop/.../some-document.docx.
Concrete local drift observed after restart:
Thread A
state_5.sqlite threads.title:
long first prompt beginning with an absolute file path and document-editing instructions
session_index.jsonl:
older entry: long absolute path title
later entry: "Course material revision"
Thread B
state_5.sqlite threads.title:
long first prompt beginning with an unzip/package path and task details
session_index.jsonl latest thread_name:
"Homepage design and VIP features"
Thread C
state_5.sqlite threads.title:
first prompt about adding an email module
session_index.jsonl latest thread_name:
"Email module development"
I also observed a successful Desktop app-server rename request in the app log:
So the app/server path for rename is being exercised, but the SQLite threads.title rows remain stale while session_index.jsonl carries the later concise names. In one case, session_index.jsonl also has multiple entries for the same thread id, with the later entry being the desired short name.
Repro steps from the Desktop side:
Open Codex Desktop on macOS.
Start or resume a local thread whose first user message begins with a long absolute path and detailed task text.
Let the app generate or set a concise thread name later.
Restart Codex Desktop.
Compare:
~/.codex/session_index.jsonl latest thread_name for that id
~/.codex/state_5.sqlitethreads.title for the same id
the title shown in Desktop Projects/sidebar surfaces
Expected:
Rename/title generation should keep session_index.jsonl and state_5.sqlite.threads.title consistent.
Desktop sidebar/list surfaces should prefer the latest explicit/generated thread name, not the stale first prompt or path.
This is especially noticeable on Desktop because long path-derived titles occupy the whole sidebar row and make project history difficult to navigate.
Yes — here is a repro-oriented version focused on the user-visible behavior rather than the internal diagnosis.
User-visible repro shape
The easiest way to see the problem is to start from a thread whose first/title text is short or stale, then let a later explicit/generated rename give it a different, more useful name.
Steps
Start Codex and create a new thread with an initial prompt that will produce an initial title, for example:
server vm
Let the thread be saved normally.
Rename the same thread to a different title, for example:
Provision server VM
This can be through the normal rename/title-generation path that writes the new thread name into the session index.
Exit/restart Codex so future resume/list/search paths read persisted metadata rather than only live in-memory state.
Try to resume/search by the new visible title:
codex resume 'Provision server VM'
Compare the persisted metadata for the same thread id:
rg '019c4b73-a91e-7640-9ef6-b1bf18951bb6|Provision server VM|server vm'~/.codex/session_index.jsonl
sqlite3 ~/.codex/state_5.sqlite \
"select id, title, first_user_message from threads where id = '019c4b73-a91e-7640-9ef6-b1bf18951bb6';"
Replace the id with the new thread id if reproducing from scratch.
Actual behavior observed
For the concrete thread I reported:
thread id: 019c4b73-a91e-7640-9ef6-b1bf18951bb6
latest session_index.jsonl name: Provision server VM
SQLite threads.title: server vm
On affected CLI paths / older builds, this can make the new visible title fail as a direct resume key:
ERROR: No saved session found with ID Provision server VM. Run `codex resume` without an ID to choose from existing sessions.
while the same session can still be found from picker-style flows that hydrate or merge names differently.
Expected behavior
After a thread rename, the same thread id should have the same effective title in both persistence layers:
append-only session_index.jsonl records the new name, and
SQLite threads.title is updated/best-effort synced to the same new name.
That way title-based resume/search/list behavior does not depend on which persistence layer a given surface uses.
Why this is user-visible
The visible symptom is not the database mismatch itself; it is that the user sees or expects the renamed title, but title-based lookup/search can still behave as if the old title is authoritative. On Desktop/sidebar surfaces this also shows up as stale or long first-prompt titles continuing to occupy the row even after a concise generated/renamed title exists elsewhere.
it calls state_db.update_thread_title(thread_id, &name) before append_thread_name(...).
Remaining issues found in the blitz review:
[MEDIUM] Existing stale SQLite titles can still mask newer session_index names codex-rs/thread-store/src/local/read_thread.rs:304 stored_thread_from_sqlite_metadata() trusts any distinct SQLite threads.title and only consults session_index when the SQLite title is missing/non-distinct.
Related paths:
So a pre-existing split-brain row such as SQLite title server vm + latest session_index name Provision server VM can still surface the old SQLite title on read/list/search-style paths unless the stale row is repaired or latest session_index is preferred.
[MEDIUM] State DB reconcile preserves stale explicit SQLite titles codex-rs/rollout/src/state_db.rs:515
Reconcile calls metadata.prefer_existing_explicit_title(&existing_metadata), so an existing stale-but-distinct SQLite title is preserved rather than repaired from the latest session_index name.
[MEDIUM] Derived title patches can still overwrite an explicit name in SQLite codex-rs/thread-store/src/local/update_thread_metadata.rs:245 ThreadMetadataPatch::title is documented as a best-effort title derived from history, but it is applied unconditionally:
That can recreate the split-brain state: SQLite gets a later derived title while session_index still has the explicit user-facing name. The current test metadata_patch_applies_title_over_existing_name appears to encode this behavior.
Suggested minimal fix shape:
Preserve an existing explicit/user-set name when applying derived patch.title unless patch.name is also present.
During read/list/search/reconcile, compare the latest session_index name for the thread and either prefer it or backfill threads.title when it differs from stale SQLite.
Add regression coverage for: SQLite title = old, latest session_index name = new, then read/list/search/resume surfaces the new name and does not let the stale SQLite title win.
Net: the original future-rename write path seems fixed, but legacy drift/backfill and derived-title overwrite cases still make this issue relevant.
Additional reproduction: Windows Desktop + WSL with a CODEX_HOME transition
I can reproduce the user-visible title divergence on Codex Desktop for Windows when the selected agent is WSL and the Desktop WSL app-server's CODEX_HOME changes.
Environment:
Codex Desktop: 26.715.2305.0
Bundled WSL runtime recorded by the task: 0.145.0-alpha.18
Runtime: WSL2
Original CODEX_HOME: Windows-mounted directory
Current CODEX_HOME: WSL-native directory
SQLite home remains WSL-native/shared
Sanitized observations for one task ID:
The task was created by the WSL agent while CODEX_HOME pointed to the Windows-mounted home.
The original home's session_index.jsonl has two entries for the same task ID:
the initial first-prompt-derived title
a later concise generated/renamed title
After changing the WSL app-server to the WSL-native CODEX_HOME and restarting Desktop, the new home's session_index.jsonl has no entry for that task ID.
Desktop/shared SQLite can still resolve and continue the same task ID.
A direct thread read on the current WSL host returns no explicit title and falls back to the initial-message preview.
The Windows-side metadata surface continues to show the later concise title.
Result: the same task ID appears with two different titles depending on which persistence surface/home is used:
Windows-side session index: latest concise renamed title
Current WSL/shared-state read: initial-message preview fallback
This confirms the issue remains user-visible in the current build. The ordinary future rename path may now update both stores when they share one home, but an existing task discovered across a CODEX_HOME transition still does not hydrate or reconcile its latest explicit name from the rollout's owning home.
Expected behavior:
One task ID should expose one effective latest title across Desktop/WSL surfaces.
When cross-home task discovery is supported, title lookup should either:
read the latest explicit name from the rollout's owning Codex home,
migrate/reconcile that name into shared SQLite/current state, or
preserve an owning-home reference in task metadata.
This is adjacent to #33815, where the same cross-home discovery works for reading but archive routing fails. No usernames, task IDs, project paths, or transcript content are included here.
Still reproducible on macOS Desktop 26.818.31338 (build 6892).
I manually renamed existing local tasks. The sidebar showed the new names immediately, but the @ mention picker did not find them by the new titles. It worked only after the task catalog refreshed; no subsequent rename was made.
This means the stale-title/search path is still user-visible in a current desktop build. For projects with many renamed tasks, @ references are unreliable until the cache or catalog happens to refresh.
Closing for the CLI rename path: thread/name/set now updates both the SQLite title and the legacy index (#21260), included in CLI 0.162.1. If the Desktop sidebar still differs from its engine’s stored name, please file a current Desktop-specific report so we can trace that path.
Activity
github-actions commentedon Apr 1, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
etraut-openai commentedon Apr 2, 2026
Can you provide repro steps? You're describing internal details, but I'd like to understand the user-visible behaviors and the steps needed to repro the problem.
NightGlowww commentedon May 22, 2026
I can reproduce this on Codex Desktop for macOS, and it also has a visible sidebar/user-facing impact when the first prompt is long.
Environment:
User-visible symptom:
/Users/<user>/Desktop/.../some-document.docx.Concrete local drift observed after restart:
I also observed a successful Desktop app-server rename request in the app log:
So the app/server path for rename is being exercised, but the SQLite
threads.titlerows remain stale whilesession_index.jsonlcarries the later concise names. In one case,session_index.jsonlalso has multiple entries for the same thread id, with the later entry being the desired short name.Repro steps from the Desktop side:
~/.codex/session_index.jsonllatestthread_namefor that id~/.codex/state_5.sqlitethreads.titlefor the same idExpected:
session_index.jsonlandstate_5.sqlite.threads.titleconsistent.This is especially noticeable on Desktop because long path-derived titles occupy the whole sidebar row and make project history difficult to navigate.
iqdoctor commentedon Jun 9, 2026
Yes — here is a repro-oriented version focused on the user-visible behavior rather than the internal diagnosis.
User-visible repro shape
The easiest way to see the problem is to start from a thread whose first/title text is short or stale, then let a later explicit/generated rename give it a different, more useful name.
Steps
Start Codex and create a new thread with an initial prompt that will produce an initial title, for example:
Let the thread be saved normally.
Rename the same thread to a different title, for example:
This can be through the normal rename/title-generation path that writes the new thread name into the session index.
Exit/restart Codex so future resume/list/search paths read persisted metadata rather than only live in-memory state.
Try to resume/search by the new visible title:
codex resume 'Provision server VM'Compare the persisted metadata for the same thread id:
Replace the id with the new thread id if reproducing from scratch.
Actual behavior observed
For the concrete thread I reported:
019c4b73-a91e-7640-9ef6-b1bf18951bb6session_index.jsonlname:Provision server VMthreads.title:server vmOn affected CLI paths / older builds, this can make the new visible title fail as a direct resume key:
while the same session can still be found from picker-style flows that hydrate or merge names differently.
Expected behavior
After a thread rename, the same thread id should have the same effective title in both persistence layers:
session_index.jsonlrecords the new name, andthreads.titleis updated/best-effort synced to the same new name.That way title-based resume/search/list behavior does not depend on which persistence layer a given surface uses.
Why this is user-visible
The visible symptom is not the database mismatch itself; it is that the user sees or expects the renamed title, but title-based lookup/search can still behave as if the old title is authoritative. On Desktop/sidebar surfaces this also shows up as stale or long first-prompt titles continuing to occupy the row even after a concise generated/renamed title exists elsewhere.
iqdoctor commentedon Jun 9, 2026
Blitz
$code-reviewupdate on current mainChecked against current
openai/codexmain:89ac3ec27cae0000da14fbe4160a79ed465843fb(89ac3ec27cae)Short version: this looks partially fixed, but not fully closed.
What appears fixed now:
codex-rs/thread-store/src/local/update_thread_metadata.rs:502-516state_db.update_thread_title(thread_id, &name)beforeappend_thread_name(...).Remaining issues found in the blitz review:
[MEDIUM] Existing stale SQLite titles can still mask newer
session_indexnamescodex-rs/thread-store/src/local/read_thread.rs:304stored_thread_from_sqlite_metadata()trusts any distinct SQLitethreads.titleand only consultssession_indexwhen the SQLite title is missing/non-distinct.Related paths:
codex-rs/thread-store/src/local/list_threads.rs:83codex-rs/thread-store/src/local/search_threads.rs:198codex-rs/tui/src/lib.rs:697So a pre-existing split-brain row such as SQLite title
server vm+ latestsession_indexnameProvision server VMcan still surface the old SQLite title on read/list/search-style paths unless the stale row is repaired or latestsession_indexis preferred.[MEDIUM] State DB reconcile preserves stale explicit SQLite titles
codex-rs/rollout/src/state_db.rs:515Reconcile calls
metadata.prefer_existing_explicit_title(&existing_metadata), so an existing stale-but-distinct SQLite title is preserved rather than repaired from the latestsession_indexname.[MEDIUM] Derived title patches can still overwrite an explicit name in SQLite
codex-rs/thread-store/src/local/update_thread_metadata.rs:245ThreadMetadataPatch::titleis documented as a best-effort title derived from history, but it is applied unconditionally:That can recreate the split-brain state: SQLite gets a later derived title while
session_indexstill has the explicit user-facing name. The current testmetadata_patch_applies_title_over_existing_nameappears to encode this behavior.Suggested minimal fix shape:
patch.titleunlesspatch.nameis also present.session_indexname for the thread and either prefer it or backfillthreads.titlewhen it differs from stale SQLite.session_indexname = new, then read/list/search/resume surfaces the new name and does not let the stale SQLite title win.Net: the original future-rename write path seems fixed, but legacy drift/backfill and derived-title overwrite cases still make this issue relevant.
solankydev commentedon Jul 17, 2026
Additional reproduction: Windows Desktop + WSL with a CODEX_HOME transition
I can reproduce the user-visible title divergence on Codex Desktop for Windows when the selected agent is WSL and the Desktop WSL app-server's
CODEX_HOMEchanges.Environment:
CODEX_HOME: Windows-mounted directoryCODEX_HOME: WSL-native directorySanitized observations for one task ID:
CODEX_HOMEpointed to the Windows-mounted home.session_index.jsonlhas two entries for the same task ID:CODEX_HOMEand restarting Desktop, the new home'ssession_index.jsonlhas no entry for that task ID.Result: the same task ID appears with two different titles depending on which persistence surface/home is used:
This confirms the issue remains user-visible in the current build. The ordinary future rename path may now update both stores when they share one home, but an existing task discovered across a
CODEX_HOMEtransition still does not hydrate or reconcile its latest explicit name from the rollout's owning home.Expected behavior:
This is adjacent to #33815, where the same cross-home discovery works for reading but archive routing fails. No usernames, task IDs, project paths, or transcript content are included here.
rshumilov commentedon Aug 21, 2026
Still reproducible on macOS Desktop 26.818.31338 (build 6892).
I manually renamed existing local tasks. The sidebar showed the new names immediately, but the @ mention picker did not find them by the new titles. It worked only after the task catalog refreshed; no subsequent rename was made.
This means the stale-title/search path is still user-visible in a current desktop build. For projects with many renamed tasks, @ references are unreliable until the cache or catalog happens to refresh.
etraut-openai commentedon Oct 12, 2026
(response from codex)
Closing for the CLI rename path: thread/name/set now updates both the SQLite title and the legacy index (#21260), included in CLI 0.162.1. If the Desktop sidebar still differs from its engine’s stored name, please file a current Desktop-specific report so we can trace that path.