openai / openai/codex

Native goal is silently deleted from thread_goals on thread resume / after Voice Live ends

Open
#38,854 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app-server bug CLI
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

Bug description

A native goal that is created and correctly persisted gets silently deleted when the thread is resumed/rehydrated. After resuming a thread (or after a Voice Live session ends, which triggers the same rehydration path via transcript_tail_flush), get_goal returns null and update_goal(status="complete") fails with:

cannot update goal because this thread has no goal

The app-server emits thread/goal/cleared during the resume, and the row is physically removed from the thread_goals table in ~/.codex/goals_1.sqlite.

Reproduction steps (headless, no voice needed)

  1. Create a thread and a goal:

    codex exec "Call create_goal with objective 'canary goal', then call get_goal and print the raw result."
    
    • get_goal returns status: "active".
    • Confirmed in goals_1.sqlite: a row for the new thread_id exists in thread_goals (status active).
  2. Resume the same thread:

    codex exec resume <session-id> "Call get_goal and print the raw result."
    
  3. While the resumed session is running (before any model turn even completes), the runtime emits:

    app-server event: thread/goal/cleared targeted_connections=0
    

    and the row for that thread_id is deleted from thread_goals. The six pre-existing rows for older threads were untouched.

  4. get_goal on the resumed thread returns null.

Observed timeline (2026-08-16, local time)

  • 10:51:34 — goal row present in thread_goals (snapshot of the sqlite db).
  • 10:52 — codex exec resume started.
  • 11:03:37 and 11:08:37 — two thread/goal/cleared events in the runtime logs during the resume.
  • 11:14 — goal row gone from thread_goals (second snapshot).

Voice Live variant (original sighting)

When a Voice (realtime) conversation ends, the injected transcript_tail_flush message ("Realtime conversation ended...") is followed by the same goal clearing: goal active before the voice session, get_goal = null right after. This makes goal mode unusable across any voice session boundary.

Additional inconsistency

On the affected thread, create_goal is refused with:

cannot create a new goal because this thread has an unfinished goal; complete the existing goal first

while get_goal returns null — so the "unfinished goal" check used by create_goal reads different state than get_goal/update_goal.

Environment

  • codex-cli 0.145.0 (darwin arm64)
  • VS Code extension + CLI (codex exec)
  • macOS

Expected behavior

Resuming a thread (or ending a Voice Live session) should preserve the thread's active goal, or at minimum surface why it was cleared. Silent deletion makes native goals unusable for any multi-session or voice-interleaved workflow.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the resume/rehydration path and the transcript_tail_flush flow, then compare the state used by create_goal, get_goal, and update_goal with the thread_goals row in goals_1.sqlite. Reproduce the issue with codex exec and resume, observing thread/goal/cleared and the database row. Done means an active goal survives resume and Voice Live termination, with consistent behavior across the goal operations.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.