Meta: /goal failures hide DB/schema/process mismatch after goal storage changes
Summary
Several /goal failures currently collapse to a generic TUI message:
Failed to read thread goal: thread/goal/get failed in TUI
or:
Failed to set thread goal: thread/goal/set failed in TUI
The existing issues suggest this message is now covering multiple distinct root causes:
- malformed/corrupt or inconsistent SQLite state/log DBs
- DB lock/contention or multiple live Codex processes
- goals feature unavailable/disabled across surfaces
- the
0.133goal storage split fromstate_5.sqlite.thread_goalstogoals_1.sqlite.thread_goals - stale live/resumed TUI/app-server processes still querying the old table after migration 34 has dropped it
This meta issue is for the diagnostic and recovery problem: the user-facing error does not expose which root cause happened, and codex doctor can report healthy DBs while a live/resumed /goal thread still fails because the process/schema expectations are mismatched.
Sanitized local diagnostic case
Observed on macOS with current CLI reporting:
codex-cli 0.133.0
codex doctor --json reports:
config.load: okenabled feature flags: includesgoalsstate.paths: okstate DB integrity: oklog DB integrity: okgoals DB integrity: okgoals DB:<CODEX_HOME>/goals_1.sqlite- only unrelated failure: non-interactive
TERM=dumbin the diagnostic shell
Local DB state:
-- state_5.sqlite
select version, description, success
from _sqlx_migrations
order by version desc
limit 6;
shows:
34 drop thread goals 1
33 thread goal stopped statuses 1
32 threads preview 1
31 drop device key bindings 1
30 threads thread source 1
29 thread goals 1
state_5.sqlite no longer has thread_goals.
goals_1.sqlite exists, passes integrity checks, and has:
CREATE TABLE thread_goals (
thread_id TEXT PRIMARY KEY NOT NULL,
goal_id TEXT NOT NULL,
objective TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN (
'active',
'paused',
'blocked',
'usage_limited',
'budget_limited',
'complete'
)),
token_budget INTEGER,
tokens_used INTEGER NOT NULL DEFAULT 0,
time_used_seconds INTEGER NOT NULL DEFAULT 0,
created_at_ms INTEGER NOT NULL,
updated_at_ms INTEGER NOT NULL
);
However, an existing/resumed thread produced logs like:
codex_core::goals: failed to read thread goal at turn start:
error returned from database: (code: 1) no such table: thread_goals
and:
codex_core::goals: failed to pause active thread goal after interrupt:
error returned from database: (code: 1) no such table: thread_goals
The visible TUI message was still only:
Failed to read thread goal: thread/goal/get failed in TUI
The affected rollout/session metadata was created by an older CLI (0.130.0 in this local case), while the installed CLI/app resource was 0.133.x and the state DB had already applied migration 34. Process listing also showed live Codex app-server/resume processes, so this appears consistent with a stale live/resumed process or schema expectation mismatch rather than corrupted SQLite.
Why this is different from only “DB corruption”
In this local case, doctor and direct SQLite inspection both show the state/log/goals DBs are present and healthy. The failure is that some goal code path still attempts to read thread_goals from the old state DB after that table was intentionally dropped.
That is a different recovery path from “move aside corrupted state_5.sqlite* / logs_2.sqlite*.” Rebuilding healthy DBs may not be the right instruction when the root issue is a stale process or post-migration schema split.
Related issues
- #20598: generic
/goalset failures; also documents the 4000-character limit / short goal workaround. - #20841: exact
Failed to read thread goal: thread/goal/get failed in TUIsymptom; comments mention logs/state DB sidecars and multiple Codex processes. - #22942: “Goal command hides underlying state DB errors”; closed with expected launch-time DB checks in 0.131.
- #22981: Desktop resume path attempted
thread/goal/getand surfaced goal hydration failures during thread open/resume. - #23354: users can have versions/configs where
/goalis not discoverable/enabled. - #23755:
0.133migration moved goals togoals_1.sqliteand droppedstate_5.sqlite.thread_goals; closed as intentional experimental breakage. - #23340: long-running
/goalloop/logging behavior, adjacent but separate. - #13941 / #7730: skill description validation warnings; separate issue, but startup warnings can obscure the goal failure in the same TUI session.
Expected behavior
When thread/goal/get or thread/goal/set fails, the TUI should show an actionable root cause category instead of only failed in TUI.
For example:
- DB corruption / integrity failure
- Name the failing DB (
state_5.sqlite,logs_2.sqlite, orgoals_1.sqlite). - Include the SQLite error and sidecar recovery instruction.
- DB lock / multiple live process contention
- Detect active Codex processes using the same
CODEX_HOME. - Tell the user to close the listed processes or restart Codex.
- Feature disabled/unavailable
- Say
features.goalsis disabled or unsupported in this surface/version. - Point to the config key or required version.
- Post-migration schema mismatch / stale process
- Detect that
state_5.sqlitehas migration34 drop thread goalsandgoals_1.sqlite.thread_goalsexists. - If a live/resumed process still receives
no such table: thread_goals, report this as a stale process/schema mismatch. - Instruct the user to fully quit old TUI/app-server processes and start a fresh session on the current binary.
- Long goal text
- Preserve the clear “goal text exceeds 4000 characters” path and recommend putting the objective in a file.
Product-side fixes that would help
- Include the underlying app-server / SQLite error chain in the TUI failure text.
- Add a
doctorcheck for goal storage consistency: state_5.sqlitemigration stategoals_1.sqliteexistence and schema- whether stale Codex processes are still running against the same
CODEX_HOME - On
0.133+, make goal reads/writes consistently usegoals_1.sqliteafter migration 34. - Treat
thread/goal/getas non-blocking during unrelated resume/open flows unless goal state is explicitly required. - Add a targeted recovery message for the 0.133 goal DB split rather than telling users only to rebuild state/log DBs.
Current workaround
For users who hit this after upgrading or resuming older goal threads:
- Fully quit all Codex TUI/Desktop/app-server processes using the same
CODEX_HOME. - Start a fresh Codex session with the current binary.
- Avoid resuming the stale active goal thread if it was created pre-migration.
- Recreate the goal with a short objective, pointing at a file for detailed instructions.
Only move aside SQLite DBs if doctor, logs, or PRAGMA integrity_check actually indicate DB corruption or migration checksum failure.
13 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Confirming this on
codex-cli 0.133.0with a live TUI session.Environment:
Darwin 25.5.0 arm64 arm3.6.10gpt-5.5codex doctor --json: overall statusokstate.paths: state/log/goals DBs inspectable and integrity checks okgoalsfeature flag enabled~/.codex/goals_1.sqliteexists and containsthread_goalsselect count(*) from thread_goals;returns0Observed TUI symptom:
Relevant log lines from
~/.codex/log/codex-tui.logrepeatedly show:and:
Local source inspection matches the migration/split hypothesis:
state_5.sqliteis the state DB.goals_1.sqliteis the goals DB.state/migrations/0029_thread_goals.sqloriginally createdthread_goalsin the state DB.state/migrations/0034_drop_thread_goals.sqllater drops it.state/goals_migrations/0001_thread_goals.sqlcreatesthread_goalsin the goals DB.StateRuntime::init_inneropens/migrates the goals DB and wiresthread_goals: GoalStore::new(goals_pool).So this does not look like malformed goal text. It looks like a live/resumed TUI path or stale DB handle still querying a connection without the post-split
thread_goalsschema, while direct inspection ofgoals_1.sqliteis healthy.Suggested fix direction:
/goal getafterstate_5.sqlitemigration 34 has droppedthread_goalsandgoals_1.sqlite.thread_goalsexists.no such table: thread_goals, refresh/migrate the goals DB handle, and retry once.Confirming on Linux/SSH with a stale app-server after upgrading to
codex-cli 0.133.0.Environment:
CODEX_HOME=/home/ubuntu/.codexcodex-cli 0.133.0codex app-server daemon versionreportedcliVersion=0.133.0andappServerVersion=0.132.0Failure:
/goalthread:019e3295-da82-76a0-9466-597d8578a26fstate_5.sqlitehad migration 34 recorded:state_5.sqliteno longer hadthread_goalsgoals_1.sqliteexisted, passedPRAGMA integrity_check, and had the restoredthread_goalsrowRecovery that worked:
~/.codex/goals_1.sqlitefrom the session JSONLthread_goal_updatedhistory, after taking a backup, if migration lost it.appServerVersionmatchescliVersion(0.133.0).Verification after restart:
codex app-server daemon versionreportedcliVersion=0.133.0,appServerVersion=0.133.0thread/resumewithclient_version="0.133.0"get_goal {}executed successfully for the restored threadno such table: thread_goalswarning did not reappearThis supports the stale-process/schema-split diagnosis: the DBs can be healthy, but a pre-update app-server can keep querying the old
state_5.sqlite.thread_goalspath after migration 34 dropped it.I am seeing the same or very similar issue on Codex Desktop for Windows.
Environment:
Symptoms:
Failed to set goalFailed to clear goalI tried:
codex --logoutcodex logingoals_1.sqlite,goals_1.sqlite-wal,goals_1.sqlite-shmLocal DB checks:
goals_1.sqliteexistsPRAGMA integrity_checkreturnsokthread_goalstable existsThis looks related to the 0.133 goal storage split / stale process / schema mismatch described here, but I am seeing it in Codex Desktop rather than CLI/TUI.
<img width="562" height="46" alt="Image" src="https://github.com/user-attachments/assets/4711ec8b-1e77-4267-9fb9-3e09b0128a8f" />
<img width="394" height="53" alt="Image" src="https://github.com/user-attachments/assets/03178078-1a1c-4a35-b9fe-9ef5c5b88fad" />
I second this; I have the exact same error toast popping up in Codex Desktop, and none of the remedies worked for me either.
I am also seeing this from the Codex macOS Desktop app, and the current UI makes it hard to self-diagnose.
Environment:
019e51ca-c9bf-7c73-b6b9-c834e41f7cd7Issue:
When I try to set a Goal in an existing Codex Desktop session, the app shows only a generic toast:
There is no actionable detail about why it failed. The message does not indicate whether the root cause is goal text length, network/backend failure, account/feature availability, repository/session state, DB/schema mismatch, permissions, or something else. As a result, I cannot tell whether I should shorten the goal, restart Codex, create a fresh session, change permissions, update the app, or report a backend issue.
Expected behavior:
If setting a Goal fails, the Desktop app should surface a more specific reason or at least a diagnostic hint, for example:
Even exposing a short error category plus a retry/recovery suggestion would make this much easier to troubleshoot.
TLDR: At some point in the last few days openai changed the way the database works and a bug in the app-server was preventing it from restarting leaving the CLI with one view of how goals work and the backend with another.
I haven't 100% confirmed the analysis but killing it and restarting did fix the problem.
======
• I’ll treat this as a small live diagnostic rather than guessing from the symptom. I’m loading the project’s required standards plus the debugging workflow, then I’ll check whether the thread goal endpoint is failing in this
session or just in the TUI surface.
• I reproduced it from this session: the goal read fails because the backing database does not have the expected thread_goals table.
is the user-facing wrapper around this lower-level error:
no such table: thread_goals
Likely causes:
[snip]
• Got it. I’ll inspect first and keep this non-destructive: identify the thread-state DB, read schema/version evidence, and only propose or run a bounded migration if there’s an obvious official path. I’ll ask again before deleting,
recreating, or overwriting any state.
[snip]
• I’m using the systematic debugging path here: first reproduce, then locate the storage layer, then compare it with whatever migration/schema code exists. I’m also doing a quick memory pass because this is in the Elspeth workspace
and prior local-tooling context may save us from poking the wrong file.
[snip]
• The sandbox is now blocking ordinary discovery commands like find/ls, which I need to locate the local Codex state DB. I’m going to request a narrow non-destructive read approval rather than guessing where the database lives. (ed: lol)
[snip]
• The state file is visible now: /home/john/.codex/goals_1.sqlite plus WAL/SHM companions. There’s also a prior rollout summary explicitly mentioning a goal-state footgun, so I’m going to inspect that and the live DB schema before
touching anything.
[snip]
• Important correction from the live read: /home/john/.codex/goals_1.sqlite does have thread_goals now. That means the missing-table error is either coming from a different DB connection/path, or from a stale long-lived process/
connection that hasn’t picked up the migrated schema. I’m checking which file the running Codex app server actually has open.
[snip]
• The app server process has state_5.sqlite and logs_2.sqlite open, but not goals_1.sqlite. Since the thread_goals schema exists only in goals_1.sqlite so far, the current hypothesis is a DB split/migration mismatch: goal storage
was migrated into one DB, while the running goal endpoint is querying another.
[snip]
• The migrations tell the story: state_5.sqlite had thread goals, then thread goal stopped statuses, then drop thread goals; goals_1.sqlite has the replacement thread_goals table. So the root cause is likely a stale app-server
process still running old goal SQL against state_5.sqlite after the DB was migrated to the split goals DB. Next I’m checking process age and restart mechanics.
[snip]
• The app server is old: it started on Thursday, May 21, while the DB migrations showing drop thread goals are already installed. That matches the stale-process hypothesis cleanly. I’m checking whether Codex exposes a daemon restart
command so I can use the intended control path instead of poking process IDs.
[snip]
• Confirmed: the running app server is 0.132.0, while the CLI is 0.133.0. That explains it: 0.133.0 migrated goal storage out of state_5.sqlite, but the old 0.132.0 server is still querying the old table location. I’m restarting the
managed app-server daemon now, then I’ll re-check the version and goal read.
• Restart did not run because this daemon was started in unmanaged mode, so the CLI refuses to manage it. I’m checking the stop path and the control files before using process-level termination; the clean target is the old app-
server pair, not the active TUI clients.
[snip]
• At this point the least invasive real fix is to restart the old unmanaged app-server so it comes back on the current CLI/schema. Because the normal daemon command refuses to manage an unmanaged process, I’m going to launch a
detached restart helper that kills only the two old app-server PIDs and then starts the daemon through codex app-server daemon start.
[snip]
ERROR: remote app server at
unix:///home/john/.codex/app-server-control/app-server-control.socktransport failed: WebSocket protocol error: Connection reset without closing handshake (ed: boom headshot)Follow up: it turned out not to be related to the SQLite state at all. In my config the feature was simply not enabled. Even though the
/goalcommand was showing while prompting, it just gave the error above.Setting
goalsto enabled and then fully restarting Codex solved it./goalis now working as expected.@Daschi1, thanks for posting that diagnosis. The
goalsfeature flag is enabled by default in CLI0.133.0. The latest app includes this newer CLI binary. That means you shouldn't need to manually enable thegoalsfeature flag in your config file.Is it possible that you have an older codex app server running locally? Check for any background "codex" processes that are running. That would explain the problem you're seeing because the newer app (or TUI) would try to connect to the older app server.
@etraut-openai Follow up after more testing:
I killed all Codex processes first, so there was no
codex.exe/Codex.exeprocess left in Task Manager. Then I removed thegoals = trueline fromconfig.tomland started Codex again.With that config,
/goalshowed up in the prompt box, but sending it showed the same error toast again. Pressing Enter on/goalstill visually selected goal mode, similar to plan mode, but sending failed.One odd detail: when trying to clear it again, the toast said
failed to clear goalinstead offailed to set goal. It still removed the selected goal mode visually, but the input placeholder stayed in the goal/steer state, showingFollow upinstead of the normalAsk for changes.Then I closed Codex again, added this back:
After starting Codex again,
/goalworked normally with the full UI.About Codex shows:
I also do not see an update indicator in the top-left corner, so this looks like the latest Desktop build available to me.
I rechecked the backend version too. The backend binary in this Desktop install is
0.133.0-alpha.1, not final0.133.0.The command I used was:
which prints:
One useful edge case for the diagnostic/recovery logic:
On Linux/tmux,
codex app-server daemon versionshowed a stale local server:The normal recovery did not work:
returned:
After stopping the old unmanaged
codex app-server --listen unix://process pair and starting the daemon again, version matched:✅ A fresh TUI resume after that did not produce a new
thread/goal/get failed/no such table: thread_goalsline.The non-obvious part is not the process kill. It is that Codex can already detect the bad state (
appServerVersion != cliVersion) but the suggested restart path can fail because the server is unmanaged. A useful recovery message would be: old unmanaged app-server is running; stop that stale server and start the managed daemon. No SQLite deletion was needed in this case.This
/goalfeature is now enabled by default in the latest version of the app and the CLI.We have received some reports of db corruption, and we've traced the problem to a bug in sqlite. We've updated the version of sqlite that we're using, but there's a possibility that the sqlite db on your system is corrupt. If you are still seeing
thread/goal/getfailures, that's the most likely cause. You can work around this by deletingCODEX_HOME/.codex/goals_1.sqlite*andCODEX_HOME/.codex/state_5.sqlite*and restarting codex. It will reconstruct these db files.Related downstream profile/stat case filed here: #26891
The local shape overlaps with this thread (
goals_1.sqlite.thread_goalsexists butcount(*) = 0, plus long-running/goalsession history in JSONL), but the user-visible symptom is different: Codex ProfileLongest taskremains stuck at 3h48m even after a completed 8h+/goalrun that occurred after the Profile feature was visible.That suggests there may be two layers to watch:
I linked this meta issue from #26891 so the two reports stay connected.