Skip to content

Thread metadata can store full first user message as title, causing huge active titles #21154

Closed

Description

@clairernovotny

What version of Codex are you using?

  • Codex.app: observed 26.429.30905 from the running app sample/process metadata
  • Codex CLI: codex-cli 0.128.0
  • Platform: macOS 26.4.1 build 25E253, arm64

What issue are you seeing?

Codex stores the full first user message as the thread title in ~/.codex/state_5.sqlite for some CLI/ACP/VS Code-origin sessions. This creates extremely large active thread titles and appears to make the Electron app sluggish when switching chats / rendering the thread picker.

Local evidence from state_5.sqlite:

select count(*) as rows,
       sum(length(title)) as title_chars,
       sum(length(first_user_message)) as first_msg_chars,
       max(length(title)) as max_title,
       max(length(first_user_message)) as max_first_msg
from threads
where archived=0;

Result:

134|14610549|14614033|675773|675773

The pathological subset is concentrated in RepoPrompt/ACP-like sessions:

select count(*) as rows,
       sum(case when title=first_user_message then 1 else 0 end) as exact_dupes,
       sum(length(title)) as title_chars,
       sum(length(first_user_message)) as first_msg_chars
from threads
where archived=0
  and source='vscode'
  and cwd='/'
  and title like '<codex reminder>%';

Result:

56|56|13944507|13944507

So 56 active rows have title == first_user_message, totaling ~13.9 MB of title text. 39 active rows have titles over 100 KB; the largest title is 675,773 characters.

Sample shape, sanitized:

source=vscode
cwd=/
title length=675773
first_user_message length=675773
title prefix=<codex reminder>You are operating in text only mode...

The actual rollout transcript is already stored separately via rollout_path, so the SQLite title field should not need to contain the entire first prompt.

Why this looks like a Codex metadata extraction bug

In codex-rs/state/src/extract.rs, apply_event_msg sets metadata.title directly from the stripped full user message when the title is empty:

EventMsg::UserMessage(user) => {
    if metadata.first_user_message.is_none() {
        metadata.first_user_message = user_message_preview(user);
    }
    if metadata.title.is_empty() {
        let title = strip_user_message_prefix(user.message.as_str());
        if !title.is_empty() {
            metadata.title = title.to_string();
        }
    }
}

user_message_preview also returns the full stripped message. Then codex-rs/state/src/runtime/threads.rs upserts both title and first_user_message into the threads table.

This differs from the external-agent session import path, which already has SESSION_TITLE_MAX_LEN: usize = 120 and uses summarize_for_label() to cap fallback labels.

Expected behavior

  • threads.title should be a bounded display label, not the raw first user message.
  • The fallback title path in state/src/extract.rs should use the same short-label logic or another hard cap.
  • Ideally first_user_message should either be bounded as preview data or excluded from hot UI list paths when very large.
  • Existing oversized titles should not cause the app to become sluggish when switching chats or rendering the thread list.

Actual behavior

  • Large ACP/VS Code-origin sessions can leave threads.title as a hundreds-of-KB prompt.
  • The title is duplicated into first_user_message for those rows.
  • Codex.app chat switching/thread navigation becomes sluggish; the live Electron renderer was observed with high CPU and a multi-GB physical footprint while investigating this state.

Reproduction sketch

  1. Start a Codex session through a CLI/ACP/VS Code client that sends a very large first user message and does not explicitly set a short thread name.
  2. Allow Codex to record/backfill thread metadata into ~/.codex/state_5.sqlite.
  3. Inspect threads.title for that thread.
  4. Observe that the title can be the entire first user message rather than a bounded label.

Related

Possibly related to broad app startup/thread-list performance reports such as #16158, but this issue is specifically about the unbounded thread title metadata path.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on May 5, 2026
  2. github-actions commented on May 5, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. clairernovotny commented on May 5, 2026

    @clairernovotny
    Author

    I have a candidate fix prepared here:

    https://github.com/openai/codex/compare/main...clairernovotny:codex:fix/state-thread-title-fallback?expand=1

    This keeps first_user_message unchanged, but changes the EventMsg::UserMessage fallback title path in codex-rs/state/src/extract.rs to use the same short-label behavior as external-agent fallback labels: first trimmed line, capped at 120 chars, with max_len - 3 chars plus ... when truncated.

    Local validation:

    • Added a regression test that failed before the fix and passes after it.
    • cargo test -p codex-state passes.
    • cargo fmt --all -- --check passes.
    • cargo clippy -p codex-state --all-targets -- -D warnings passes.

    I could not open the upstream PR from this account because I am not a collaborator; GitHub returned clairernovotny does not have the correct permissions to execute CreatePullRequest.

  4. clairernovotny commented on May 5, 2026

    @clairernovotny
    Author

    Closing this narrower root-cause issue in favor of #21211, which now tracks the broader performance problem: title bloat, reconciliation repopulation from JSONL/session index, oversized thread-list previews, and large-thread loading UX. The candidate compare branch linked above is still useful context, but the fix should be handled as a systemic bounded-metadata/performance issue rather than only this one fallback path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingperformancesessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions