Codex Desktop chats disappear from sidebar after restart when the first request is supplied as a pasted-text attachment

Open 💬 15 comments Opened Jul 21, 2026 by sdfox945
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

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

26.715.7063.0

What subscription do you have?

Pro

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

Summary

Codex chats created with a large initial request supplied through an attached pasted-text.txt file can disappear from the sidebar after the desktop app is fully closed and reopened.

The transcript is not deleted. The rollout, SQLite thread row, session-index records, title, archive state, and project assignment remain intact. However, Codex leaves the SQLite first_user_message and preview fields empty. The sidebar’s visible-thread indexes require preview <> '', so the chat is omitted when the sidebar reloads after restart.

This has happened repeatedly and is reproducible with attachment-based initial prompts.

Latest affected chat

  • Title: Phase 1E-B3B2
  • Thread ID: 019f8262-5ee8-7a00-bede-a4b083facf6b
  • Thread type: normal user thread
  • Project: local project peptide-tracker-native
  • State: active, not archived
  • Rollout: present and readable
  • Session-index records: present, including the renamed title
  • Project assignment: correct in both global-state files
  • SQLite integrity: ok
  • Foreign-key violations: 0
  • first_user_message length: 0
  • preview length: 0

What steps can reproduce the bug?

Reproduction steps

  1. Open a registered local Codex project in the Windows desktop app.
  2. Create a new Codex chat.
  3. Make the initial request a large pasted request that Codex represents as an attached pasted-text.txt file.
  4. Allow the chat to run normally.
  5. Rename it to a short title.
  6. Fully close the ChatGPT/Codex window and exit it from the system tray.
  7. Reopen the desktop app.
  8. Select the same project and check both project-grouped and Chronological sidebar views.

What is the expected behavior?

Expected behavior

The chat should remain visible after restart because:

  • Its rollout transcript exists.
  • Its SQLite thread row exists.
  • It is active and classified as a user thread.
  • Its session-index records exist.
  • Its project assignment is valid.
  • Its title and working directory were persisted.

Additional information

Actual behavior
The chat disappears from the sidebar after restart.

Read-only inspection shows that Codex created all other metadata but failed to populate:

first_user_message = ""
preview = ""

The current SQLite database contains sidebar-visible partial indexes equivalent to:

WHERE preview <> ''

Consequently, the otherwise-valid chat is excluded when the sidebar is rebuilt from persistent storage.

The database backfill state is already marked complete, so reopening Codex does not repair the missing fields.

Repeated pattern

This is not an isolated thread. Three recovered chats previously had the same condition:

  • Valid rollout
  • Valid SQLite row
  • Valid session-index metadata
  • Correct project assignment
  • Empty first_user_message
  • Empty preview
  • Missing from the sidebar

Those chats also began with requests represented through pasted-text attachment wrappers. Populating only the two missing fields restored their visibility across multiple full restarts.

Simple chats whose first message was ordinary inline text received nonempty preview fields and persisted normally.

This suggests that the first-message metadata extraction path does not correctly handle an initial user message represented as an attachment wrapper, possibly when injected plugin or environment context precedes it.

Relevant rollout structure

For the latest affected chat:

  • The rollout header contains the correct thread ID and working directory.
  • The first recorded user-role item contains injected plugin context.
  • The next genuine user item references the attached pasted-text.txt.
  • Codex processes the request successfully and records subsequent responses.
  • No corresponding metadata error is reported in the logs.
  • The thread title, session index, and project assignment are still written successfully.

This appears to be a silent metadata-ingestion failure rather than transcript loss or SQLite corruption.

Impact

  • Active work appears lost after an application restart.
  • The user cannot resume the chat through the normal sidebar.
  • Chronological view and Archived Chats do not help because the row fails the database visibility predicate.
  • Local database recovery is required to make the chat visible again.
  • Repeating that recovery is risky and should not be necessary for newly created chats.

Temporary workaround

Starting a chat with a short ordinary inline message, waiting for the first response, and sending the large attached request in a second turn appears likely to avoid the problem. This is only a workaround and has not been established as an official solution.

Requested investigation

Please investigate the Codex Desktop path that derives and persists first_user_message and preview for a new thread when its initial genuine request is represented by a pasted-text attachment.

In particular, please verify:

  1. Whether injected plugin/environment user-role items interfere with first-message selection.
  2. Whether attachment-wrapper messages are intentionally excluded without a fallback to their referenced pasted text.
  3. Why title/index/project metadata succeeds while both visibility fields remain empty.
  4. Why completed backfill state prevents later correction.
  5. Whether the sidebar should exclude otherwise-valid user threads solely because preview is empty.

Please also provide a supported, version-aware way to rebuild thread visibility metadata from intact rollout files. A supported repair or diagnostic function would be much safer than direct SQLite intervention.

I can provide sanitized counts, schemas, index definitions, relevant timestamps, and short log excerpts if needed. I will not send authentication files or full private transcript contents.

View original on GitHub ↗

15 Comments

github-actions[bot] contributor · 1 month ago

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

  • #33652
  • #33309

Powered by Codex Action

sdfox945 · 1 month ago

This also causes an issue where active sessions don’t appear correctly when using the remote feature in the phone app. More details from Codex are included below:

Yes—there are two related but distinct problems.

  • “Verify chat persistence” is healthy:
  • preview: 75 characters
  • first_user_message: 75 characters
  • Created normally under the current installation.
  • “Phase 1E-B3B2” is still incomplete:
  • preview: 11,934 characters
  • first_user_message: 0 characters
  • This missing field likely excludes it from the Remote task list, even though the repaired preview makes it visible locally.
  • “Phase 1E-B2D” has both fields populated, but it was restored from the previous installation:
  • preview: 2,734 characters
  • first_user_message: 2,734 characters
  • SQLite’s title is still the original “Phase 1E-B3A is approved…” prompt.
  • “Phase 1E-B2D” exists only as a local session_index.jsonl rename.
  • There is no Remote/synchronization identifier in the SQLite thread row or rollout header.

The evidenced explanation is:

  1. Local sidebar visibility uses the local database/index and requires a nonempty preview.
  2. Remote access goes through the host’s Remote Control connection and maintains additional host-side registration state.
  3. Restoring SQLite, the session index, and rollout files reconstructs local tasks but apparently does not announce historical thread IDs to the Remote catalog.
  4. B3B2 also has the concrete metadata defect of an empty first_user_message.
  5. B2D looks locally complete, but its imported thread ID was never registered with the current installation’s Remote task catalog. Its local rename probably would not be visible remotely either.

All three rollout headers otherwise match: Codex Desktop, source=vscode, thread_source=user, the same CLI version, repository, branch, model provider, and normalized working directory. The Remote connection itself is healthy and connected; no logs show either missing thread ID being requested, rejected, or dropped.

OpenAI’s documentation says Remote should expose “the same projects [and] chats” on the connected host. Your restored tasks violating that expectation supports treating this as a product defect, not intended behavior. [OpenAI Remote connections documentation](https://learn.chatgpt.com/docs/remote-connections)

I would not alter B2D’s SQLite fields speculatively. The appropriate next bounded repair investigation would be:

  • Correct B3B2’s first_user_message from its preserved first request, while retaining the existing preview.
  • Determine whether reopening or sending a harmless follow-up to each task causes the current Remote host to announce its ID.
  • If B2D remains absent, provide OpenAI Support with its ID and the Remote environment/server details from the logs; there is no evidenced local database flag we can safely manufacture to register it remotely.

No files, databases, processes, or application state were changed during this inspection.

embrisa · 1 month ago

Comment written by GPT 5.6 after fixing the issue on my machine

"""
Confirmed independently on macOS 26.1 using Codex Desktop 26.715.72359 (build 5718), CLI 0.145.0-alpha.18.

A completed thread created from a large initial prompt represented as pasted-text.txt disappeared from the sidebar.

Read-only inspection confirms:

thread ID: 019f72ba-5cae-7320-a17f-1493b218ba0a

title, CWD, project association, and rollout file are intact

thread is active and archived = 0
first_user_message length = 0
preview length = 0

the thread can still be opened directly by ID, but normal thread listing omits it
This matches the reported preview <> '' visibility failure exactly and confirms the defect is cross-platform.
"""

chumdesign · 27 days ago

Additional Windows reproduction: missing Remote/mobile entry caused a dangerous duplicate run

I independently reproduced this exact defect in Codex Desktop on Windows with a local project thread whose initial substantive request was supplied only through the automatically generated pasted-text.txt attachment wrapper.

Sanitized evidence

  • The completed transcript remained intact and could still be read directly by thread ID.
  • The threads row remained active: archived = 0, archived_at = NULL, with the correct title, CWD, and project directory.
  • Both display fields were empty: first_user_message length = 0, preview length = 0.
  • The thread had no entry in local_thread_catalog.
  • Normal thread listing omitted it even though direct thread reads succeeded.
  • Manually dragging the task back into the project, pinning it, and renaming it could make it appear temporarily, but it disappeared again after restart, including from Pinned.
  • Renaming did not backfill first_user_message, preview, or the catalog entry.
  • A same-directory fork of the intact completed thread produced a new thread ID that was immediately cataloged under the correct project and remained visible; the original thread stayed intact.

Safety impact beyond sidebar visibility

The affected task also failed to appear through Remote on the user's phone. Because the user could not see the existing task remotely, they reasonably assumed it was unavailable and started the same task again from the phone. This created overlapping agent activity against the same repository and linked development environment. The project represented approximately one week of work and was nearly damaged by the duplicate run.

This makes the bug more than a cosmetic history problem: a missing catalog entry can cause users to launch duplicate high-impact work against the same project while the original task still exists or is still running.

Requested behavior

  1. An attachment-only initial request must always create durable, non-empty task metadata.
  2. If the actual pasted text cannot be extracted immediately, use a safe fallback title/preview such as pasted-text.txt (or its attachment label) rather than omitting the task entirely.
  3. Active, unarchived tasks must not be excluded from local or Remote/mobile listings solely because preview or first_user_message is empty.
  4. Startup/reindex should repair missing display metadata from the attachment label, generated title, or intact rollout.
  5. Renaming, pinning, reopening, or moving a task into a project should trigger the same repair/backfill path.
  6. Remote should surface the same active task inventory as Desktop, including attachment-backed tasks.
  7. Please consider a duplicate-execution warning when another task for the same project/repository is already active but missing from the Remote catalog.

I can provide the affected thread ID and additional sanitized catalog/SQLite diagnostics privately if maintainers need them. I am intentionally not posting the private transcript, database, attachment contents, or repository details publicly.

Johnjohntasty · 25 days ago

Additional reproduction: Windows Desktop over SSH to Linux, five consecutive affected root threads

I reproduced this on Windows Codex/ChatGPT Desktop connected over SSH to a Linux host, with Codex CLI 0.146.0 and a shared remote CODEX_HOME.

Reproduction pattern

Within one remote project, five newly created Desktop root threads were affected consecutively:

  • source = vscode
  • thread_source = user
  • model_provider = openai
  • archived = 0
  • rollout JSONL exists and is readable
  • SQLite threads row exists
  • session_index.jsonl contains the thread ID
  • generated title exists
  • first_user_message = ''
  • preview = ''

The threads remained usable during the active Desktop process, but disappeared after Desktop/app-server restart. They were then missing from both the Desktop sidebar and the normal CLI resume picker.

No transcript loss occurred. Direct reads/resume by exact thread ID still worked.

App-server evidence

Using the app-server WebSocket protocol for read-only inspection:

  • thread/read succeeded for the affected thread.
  • thread/list with useStateDbOnly = true still omitted the newest affected thread.
  • Older comparison threads in the same project with non-empty first_user_message and preview were returned normally.

This shows the omission is not caused by a missing rollout, missing SQLite row, missing session-index entry, archive state, CWD mismatch, source kind, or provider mismatch. The active thread becomes undiscoverable because its durable display metadata is empty.

Relevant rollout structure

The affected rollout begins with:

  1. injected developer/context records;
  2. a user-role injected plugin recommendation block (<recommended_plugins> ...);
  3. the genuine user request represented through a generated pasted-text/attachment wrapper.

The request executes normally and the title is generated, but first_user_message and preview remain empty. This suggests the first-message metadata extraction path may select or skip the injected user-role record and then fail to fall back to the genuine attachment-backed request.

Additional observed behavior

One previously affected thread became discoverable again after it was resumed by exact ID and received a later ordinary inline user message. After that, its first_user_message and preview were populated and it remained visible.

Requested safeguards

  • Do not exclude an active, unarchived user thread solely because preview or first_user_message is empty.
  • Fall back to the generated title, attachment label, or attachment-backed user request when first-message extraction fails.
  • Rebuild/backfill these fields during startup/reindex from the intact rollout.
  • Ensure Desktop and CLI history discovery use the same durable inventory for remote SSH projects.

All diagnostics were read-only. No rollout, SQLite row, session index, or transcript content was modified. I can provide sanitized thread IDs and schema/query details privately if useful.

Motoharu-Kataoka · 21 days ago

Still reproducible on Windows package 26.803.5235.0 / app-server CLI 0.147.0-alpha.6.5

I independently reproduced the same attachment-only metadata failure in a local Windows project after a Codex Desktop update and restart.

The affected task completed before the update under CLI 0.147.0-alpha.1.2. Windows then replaced package 26.730.8199.0 with 26.803.5235.0; the current bundled app-server reports CLI 0.147.0-alpha.6.5. After restart, the task disappeared from the normal task list, but remained directly readable by its exact thread ID.

Sanitized read-only evidence

  • The rollout JSONL still exists and is readable: approximately 3.05 MB / 1,082 records.
  • The final response and completed turn are present; no terminal task error was recorded.
  • The threads row still exists with a non-empty generated title, correct CWD/project association, and archived = 0.
  • The global sidebar order and project-assignment state still contain the affected thread ID.
  • first_user_message length = 0.
  • preview length = 0.
  • name is null, while the generated title is non-empty.
  • Direct thread/read succeeds.
  • Current thread/list with useStateDbOnly = true omits the thread.
  • A second thread in the same project with both fields empty is also omitted.
  • Same-project comparison threads with non-empty previews are returned normally.

The initial genuine user item has the standard attachment-wrapper shape: it references a generated pasted-text.txt, states that the attachment contains the request, and has no inline content after ## My request for Codex:.

Current app-server query evidence

Printable SQL embedded in the currently installed codex.exe shows the list query applying:

AND threads.preview <> ''

The binary also contains a repair path equivalent to:

SET preview = first_user_message
WHERE preview = '' AND first_user_message <> '';

That repair cannot help this case because both preview and first_user_message are empty, even though the generated title and intact rollout provide safe fallback metadata.

This narrows the failure to the current app-server inventory/list path rather than transcript deletion, archive state, lost project mapping, or frontend-only rendering. The update/restart exposed the problem because the rebuilt list excludes the otherwise-valid row.

Requested fix

  1. Do not exclude active, unarchived user threads solely because preview = ''.
  2. Fall back to the generated title or attachment label when attachment-only first-message extraction produces empty metadata.
  3. Backfill both fields from the intact rollout/title during startup or reindex.
  4. Add a regression test covering an initial request represented only by a generated pasted-text attachment.

I am intentionally omitting the full thread ID, local username/path, repository name, database, rollout contents, and attached request. I can provide additional sanitized offsets, counts, and version evidence if maintainers need it.

shleder · 14 days ago

The empty first_user_message / preview case is a strong discovery mismatch: the rollout, SQLite row, session-index entries, title, and project assignment all survive, but the sidebar predicate hides the thread after restart.

I’m testing Codex Rescue against this exact boundary. It scans local rollouts independently and does not modify SQLite, session_index.jsonl, or the source transcript. It cannot rebuild the Desktop preview fields, but it should help confirm that the hidden session is durable and structurally inspectable.

If one affected chat still exists, could you run:

pipx install codex-rescue==0.1.0a3
codex-rescue sessions
codex-rescue doctor --latest

Sanitized output is sufficient—please don’t publish raw rollouts, pasted attachments, databases, prompts, project content, paths, or secrets.

https://github.com/shleder/codex-rescue

Motoharu-Kataoka · 14 days ago

@shleder Thanks. I confirmed that at least one local rollout associated with a Desktop thread matching the #34446 empty first_user_message / preview boundary is still present, and tested Codex Rescue 0.1.0a3 against it.

I used the hash-matched PyPI wheel without a global install. After reviewing the invoked source paths, I ran only lightweight_scan and doctor_session, supplying the selected rollout path directly; I did not run salvage or use --latest. Those paths contain no network operation or Codex-state write operation. Doctor did perform read-only Git inspection of the rollout's recorded CWD.

Sanitized result:

lightweight_scan.status: healthy
lightweight_scan.reason: null
lightweight_scan.first_prompt_present: false
lightweight_scan.last_prompt_present: false
doctor.status: HEALTHY
doctor.findings: [HEALTHY]
source_rollout_sha256_size_mtime_unchanged: true

A separate read-only structural check confirmed, without publishing any values, that the selected rollout's session-metadata ID matched its SQLite thread ID, a matching session-index entry was present, the attachment-wrapper shape was present, and recorded assistant output survived.

Interpretation: the bounded scanner found no malformed tail or unfinished tool call in its sampled windows and returned no prompt preview. Doctor completed its full parse with no finding recognized by 0.1.0a3. HEALTHY here is the tool-defined result; it does not prove semantic completeness or repair of the Desktop sidebar fields.

Because I supplied the rollout path directly, this confirms only that the file was present and structurally parseable at test time. It does not establish that codex-rescue sessions would enumerate the hidden thread.

I am sharing only status and boolean fields. No local session or thread IDs, timestamps, paths/CWD values, repository or project names, Git refs or SHA values, prompts, attachment contents, raw rollouts, raw database rows/files, or secrets are included here.

shleder · 13 days ago

@Motoharu-Kataoka Thanks — this is exactly the kind of real-world validation I was looking for.

One small follow-up would help close the discovery question: could you run only

codex-rescue sessions

and check whether the affected hidden Desktop thread appears in the output?

No need to run salvage, and please keep the same privacy boundary — I only need a yes/no (or sanitized matching status), not the thread ID, rollout path, prompts, database contents, project names, or other local data.

The reason this matters: your direct-path test already confirms the rollout is structurally parseable and untouched. If sessions also discovers it independently, that would validate a useful recovery/discovery case where Desktop visibility diverges from the durable local rollout.

Motoharu-Kataoka · 13 days ago

@shleder I ran the 0.1.0a3 sessions CLI entry point with its default options only. It completed successfully, but the selected affected hidden Desktop thread did not appear in the returned set.

Important caveat: 0.1.0a3 defaults to the 20 most recently modified rollouts. Therefore this negative result is inconclusive for independent discovery: it shows only that the affected thread was not surfaced by the default command, not that the scanner cannot discover it beyond the default limit.

I captured the output locally and discarded it after comparing the returned summaries against the already-known affected rollout. I am not publishing IDs, paths/CWD values, prompts, repository names, database contents, or raw output. No salvage was run.

If you want a bounded follow-up that distinguishes the 20-item cutoff from discovery behavior, please provide the exact command or limit.

shleder · 13 days ago

@Motoharu-Kataoka Thanks — that caveat is exactly what I wanted to separate.

Could you run one bounded follow-up with a larger discovery window:

codex-rescue sessions --limit 1000 --json

Please compare locally against the already-known affected rollout and reply with only whether the hidden thread appears (yes / no). No need to paste the command output, IDs, paths/CWD values, prompts, repository names, database contents, or other local data. No salvage needed.

If it appears, the earlier miss was only the default 20-item cutoff. If it still does not appear within 1000, that would be useful evidence of a real discovery gap in 0.1.0a3 rather than just ranking/limit behavior.

Motoharu-Kataoka · 13 days ago

@shleder No — the already-known affected hidden Desktop thread did not appear in codex-rescue sessions --limit 1000 --json.

JimmyYing · 12 days ago

Additional independent Windows reproduction on Desktop 26.810.7004.0

I reproduced the same attachment-backed metadata failure on Windows 10 Pro 22H2 (build 19045).

  • Desktop package observed from the running process path: 26.810.7004.0
  • Bundled CLI recorded in the affected session metadata: 0.146.0-alpha.9.2
  • Affected thread ID: 01a009fe-0b67-73a2-9723-02cc6f557261
  • Thread source: normal Desktop user thread (source=vscode, thread_source=user)

The initial substantive request was represented only by the generated pasted-text.txt attachment wrapper; the inline section after “My request for Codex” was empty. The task completed successfully and its full rollout/final answer remain intact.

Read-only verification:

  • SQLite thread row exists.
  • archived = 0
  • archived_at IS NULL
  • length(first_user_message) = 0
  • length(preview) = 0
  • Direct thread/read by exact ID succeeds and returns the full completed transcript.
  • The normal current/recent thread listing omits the ID even though it is very recent.
  • The archived-thread listing also omits it.
  • Direct deep-link navigation successfully opens the thread in the Desktop app.
  • Re-checking the current and archived listings after direct navigation still omits the thread; opening it does not repair/backfill the visibility metadata.

This matches the preview <> '' discovery failure described in the issue. It also confirms that the defect still reproduces on the newer 26.810.7004.0 Windows Desktop package and that direct reopening does not heal the empty metadata.

No transcript text, attachment contents, project files, local paths, database files, or authentication data are included here.

shleder · 6 days ago

Great diagnosis — you've already found the mechanism: the rollout, SQLite row, session-index records, title, and project assignment are all intact, but first_user_message and preview are empty, and the sidebar's visible-thread query filters on preview <> ''. So the chat isn't lost; it's invisible because a derived display field was never populated when the first request came in as an attachment instead of inline text.

That's a projection gap, not data loss — the attachment-based first prompt path skips the code that backfills preview/first_user_message into the thread row. The repair is to re-derive those two fields from the rollout (the first user turn is right there) and write them back, which is exactly the kind of reconciliation a supported reindex should do.

Full disclosure: I maintain codex-rescue (https://github.com/shleder/codex-rescue). codex-rescue diff --latest reconciles rollout vs SQLite vs session_index read-only and flags exactly this kind of field-level divergence — present on disk, empty in the projection — so you can confirm the chat is fully recoverable and produce the evidence that the preview backfill is the missing step. It never writes to the state DB, but it gives you the precise reconciliation report.

shleder · 3 days ago

Your hidden-thread tests are preserved: recursive discovery now covers nested rollouts beyond the old default window, and read-only inventory reports SIDEBAR_METADATA_EMPTY when both discovery fields are blank.

Migration update: active Codex Rescue development has moved to Vetto: https://github.com/shleder/vetto. The standalone shleder/codex-rescue repository remains public as compatibility history. User installation is now npm install --global @shleddy/vetto@next, with recovery under vetto rescue. The boundary remains read-only/copy-only and does not modify session JSONL or vendor SQLite. The newest diagnostic changes are merged into Vetto main and will be included in a later npm alpha; no source install is requested.