Repository navigation
Desktop: "Error submitting message" — turn/start times out (30s) while app-server sidecar stalls silently for minutes #27395
Description
What version of the Codex App are you using?
26.608.12217 (codex core 0.138.0-alpha.7, originator Codex_Desktop, auth mode ChatGPT)
What subscription do you have?
What platform is your computer?
macOS 26.5.1, Apple Silicon (arm64)
What issue are you seeing?
Submitting a message in a Desktop thread intermittently fails with the inline banner "Error submitting message". Re-sending the exact same message a minute or two later succeeds.
Desktop renderer log shows the composer giving up after a 30-second RPC timeout on turn/start:
2026-06-10T13:05:09.164Z warning [electron-message-handler] mcp_request_timeout
conversationId=019eb19c-84da-7933-a03c-cbfbb4e11d57 method=turn/start
pendingCount=13 requestId=654d3396-... timeoutMs=30000
2026-06-10T13:05:09.173Z error [electron-message-handler] [Composer] submit failed
cwd=~/Documents/Codex/2026-06-10/... errorMessage=Timeout errorName=Error
errorStack="Error: Timeout\n at Object.error (app://-/assets/vscode-api-....js:...)\n at ks (app://-/assets/composer-....js:...)" followUp=local mode=local
7 occurrences on 2026-06-10 (first at 10:48:42Z), zero occurrences in the preceding 13 days of desktop logs. All 7 timeouts are method=turn/start; pendingCount grows across the day (2 → 5 → 6 → 13), so requests pile up against the same app-server sidecar.
Root-cause evidence from the app-server side (~/.codex/logs_2.sqlite, logs table): the main app-server sidecar process stops emitting any log rows at all for multiple minutes, and every submit failure falls inside one of those silent windows. Example: the sidecar wrote ~1000 rows during 23:04 local while a turn was streaming, then wrote nothing from 23:05 through 23:11 — exactly bracketing three consecutive submit timeouts at 23:05:09, 23:06:50 and 23:10:33 (UTC+10 local; 13:05/13:06/13:10Z in the desktop log above).
The stalled thread's previous turn never finalizes: e.g. thread 019eb19b-dae6-7192-be60-8d0432f9587c logged its final answer and token usage at 12:57:27Z (needs_follow_up=false has_pending_input=false), then the thread never logged another line and never emitted turn/completed; the next turn/start for that thread (12:57:44Z) timed out at 12:58:14Z. The desktop also logs Received turn/started for unknown conversation for the ephemeral title-generation thread during the same window.
Possibly relevant: the stall windows coincided with elevated concurrency on the shared ~/.codex SQLite databases — 3–4 distinct codex processes (per process_uuid in the logs table) writing to logs_2.sqlite at the failure minutes vs. 1 normally (nested codex exec runs spawned by an agent, plus agent turns querying ~/.codex/state_5.sqlite / logs_2.sqlite directly). logs_2.sqlite had grown to 1.4 GB with a multi-MB WAL.
Ruled out locally: plugin hooks (UserPromptSubmit/Stop hook binaries exit in <1 s when run by hand), the notify turn-ended client (unchanged binary), network-proxy feature (same log lines appear on prior, healthy days), leftover nested codex processes (none running; only the sidecar holds the DBs), and a newly added <name>.config.toml profile-v2 file (never loaded without --profile).
What steps can reproduce the bug?
Not deterministic, but reliably reproduced today with this pattern:
- Run an agent thread in the Desktop app that heavily reads
~/.codexitself (e.g. SQLite queries against a largelogs_2.sqlite,rgover~/.codex) and/or spawns nestedcodex exec/codex --profile <name> execsubprocesses, so several codex processes share the~/.codexSQLite databases concurrently. - While that turn is running (or just after its final answer), submit another message — either a follow-up in the same thread or a message in another thread owned by the same sidecar.
- If the sidecar is in one of its silent stall windows, the submit shows "Error submitting message" after ~30 s.
- Wait 1–5 minutes; resubmitting the identical message succeeds.
Affected thread/session ids from 2026-06-10 (in case server-side lookup helps):
019eb122-5dbf-7462-ac2d-a0ea9ac9a39f, 019eb12c-1a8d-7551-990f-768161dd4a28, 019eb12d-befb-71e0-88c2-e77aaeefc885, 019eb19b-dae6-7192-be60-8d0432f9587c, 019eb19c-84da-7933-a03c-cbfbb4e11d57
What is the expected behavior?
turn/startshould be acknowledged promptly (or fail fast with a real error) even when the thread's previous turn is still finalizing or the sidecar is under I/O pressure; a queued/steered message should not surface a generic "Error submitting message".- A turn that has produced its final answer should always reach
turn/completed; the per-thread session loop should not wedge silently with no log output. - Consider rotating/pruning
logs_2.sqlite— unbounded growth (1.4 GB here) amplifies any DB-contention stall.
Additional information
- Timezone note: desktop log timestamps are UTC; app-server sqlite analysis above is local (UTC+10).
- Happy to provide redacted log excerpts or run diagnostics on request.
Activity
twentyOne2x commentedon Jun 11, 2026
Adding a current-build datapoint that matches this issue and links it to broader Desktop live-state degradation: #27601.
Environment:
Observed repeated
turn/starttimeouts while submitting a message in Desktop:The same thread later became readable and completed, so this was not data loss. The failure appears to be Desktop/app-server sidecar backlog or live-state wedging: retrying later may work, and a full Desktop quit/reopen makes sends work again temporarily.
YoneRai12 commentedon Jun 30, 2026
[app-server][Desktop][Windows][turn/start][thread/resume][notLoaded][Error submitting message]
I saw a closely related Windows Desktop variant that may be a narrower race than the sidecar stall described here.
Reproduction variant
notLoadedstate).Error submitting message. Fully restarting Codex Desktop clears the condition.This is close to this issue and #23644 because restart clears the stale/unloaded runtime state. It is related to #30704 only in the broader Windows Desktop live-state class; #30704's direct symptom is active-turn interruption from opening a local file, so I would not treat it as the primary duplicate.
Root-cause hypothesis
In the public app-server code,
turn/startcurrently callsTurnRequestProcessor::load_thread, which resolves the thread id and then requiresthread_manager.get_thread(thread_id)to already have a loaded runtime handle. If Desktop sendsturn/startwhile the UI has opened a stored thread but beforethread/resumefinishes, the app-server path can fail asthread not foundeven though the rollout exists on disk.That error shape gives the Desktop client no structured way to distinguish:
Patch proposal, if maintainers want a PR
A small app-server contract improvement would be to return a structured retryable invalid-request error for this race, for example:
{ "code": -32600, "message": "thread not loaded or not found: <thread_id>; call thread/resume and wait for it to complete before turn/start", "data": { "thread_error_code": "thread_not_loaded", "retry_method": "thread/resume", "blocked_method": "turn/start" } }The Desktop client could then disable/queue composer submission until
thread/resumecompletes, or retry after resume, instead of surfacing a genericError submitting message.The same structured error is useful for nearby methods that also need a loaded thread handle, such as
turn/steer,thread/inject-items,thread/settings/update,review/start, andturn/interrupt.Test coverage proposal
Add an app-server integration test that:
thread/resume,turn/startfor that stored thread id,thread_error_code=thread_not_loaded,retry_method=thread/resume, andblocked_method=turn/start.This keeps the client-visible contract executable and avoids piecemeal field-only assertions.
Local validation attempted
cargo fmt --all --checkfromcodex-rs: passed. It emits the existing stable-rustfmt warnings aboutimports_granularity = Itemrequiring nightly.git diff --check: passed, with only Windows CRLF replacement warnings.cargo test -p codex-app-server --test all turn_start_reports_resume_retry_for_unloaded_stored_thread.Per
docs/contributing.md, I am posting this as issue analysis/reproduction/fix outline rather than opening an unsolicited external PR.loremcdmx commentedon Jul 26, 2026
I hit this exact signature today and was able to trace it to a specific, reproducible cause: an orphaned
codex_chronicleprocess holding the Chronicle lock (#19516).Environment:
ChatGPT.app26.721.41059, Codex Framework 150.0.7871.128, macOS 26 (Darwin 27.0.0), Apple Silicon.Identical renderer log to the one in the opening post:
And the same queue pile-up —
inFlightRequestCountpinned at 6 withapp/list,skills/list,config/readandthread/listall dying withApp server request expired while queued.The cause in my case: a
codex_chronicleprocess (PID 1261, PPID 1) left over from an app instance four days earlier was still holding the lock, so the current app's sidecar could never start. It loggedWaiting to acquire lock (owned by pid=1261)5,074 times in one day.kill 1261alone fixed it — the waiting sidecar acquired the lock 20 seconds later:submit failedexpired while queuedSo for anyone landing here with the intermittent "Error submitting message": before anything else, check for a stale sidecar from a previous app launch —
— and see whether its start time predates your current app session. Details and suggested fixes in #19516.
This may not be the only path to the symptom described here (a sidecar can presumably stall for other reasons), but it is one concrete, verifiable one.
Audacity88 commentedon Aug 7, 2026
Current-build datapoint: this also occurs under severe host CPU contention.
Environment:
While two unrelated development daemons were consuming roughly 195% and 141% CPU, Codex's app-server queue stopped servicing even critical requests:
turn/start: 30-second timeout,pendingCount=16config/read: 30-second critical-priority timeoutthread/readandthread/list: rejected after 60 seconds queuedThe failures occurred in both Approve for me and Full Access, including
Error creating chat: App server request expired while queued. There was no stalecodex_chronicleprocess.I also observed 35 idle
cua_node/bin/node_replchildren under the app-server during the stall. After terminating the unrelated high-CPU processes, Codex recovered and chat creation worked again.This suggests host CPU pressure can trigger or amplify an app-server scheduling/backpressure failure. Critical chat creation, configuration, and approval traffic should remain responsive, or background hydration should be shed earlier.
genzorr commentedon Aug 7, 2026
Adding a current-build macOS datapoint with a same-workspace A/B control that appears to match this issue.
Environment
26.730.61639This has become a frequent reliability problem over the last several days, primarily in one long-lived thread.
Same-workspace A/B
Affected thread
turn/startresponse times progressed approximately as follows:For the latter three, Desktop emitted a 30-second
mcp_request_timeoutforturn/start, but the response eventually arrived and was routed. These request records showedqueueWaitMs=0.I then created a fresh thread in the same Desktop app / same project / same working directory. Its
turn/starttimes were:So the strongest local observation is:
same project + same app + fresh thread: ~30–140 ms
versus
existing affected thread: ~38–47 seconds
This argues against general backend latency, the project directory itself, or a machine-wide Desktop slowdown, and points more toward thread-local app-server/session-runtime state or request serialization.
Compaction does not recover it
The affected thread underwent multiple context compactions. Token accounting showed compaction-like resets around ~234k -> 0 and ~259k -> 0.
Later, while the slow
turn/startbehavior was still occurring, the core log reported approximately:So successful compaction did not restore normal message-acceptance latency.
I also checked the public source at
openai/codex@f2bee854a73666e1c3e922a853dda591b1a25fcf(2026-07-28). At that ref, app-serverturn/startis serialized per thread, resolves configuration/environment/workspace-root state, then submitsOp::UserInputthrough core. Pre-sampling compaction runs later inside admitted turn execution; it does not recreate the app-server per-thread serialization queue or live thread/session object. That makes it plausible for compaction to succeed while an independent thread-local acceptance/routing problem persists.At the same pinned ref,
runtime_workspace_rootsare resolved/deduplicated as paths; I did not find a recursive repository scan in theturn/startpath. The affected request configuration had many workspace roots, but the fresh-thread result in the same project is also evidence against project-wide scanning being the primary cause.What would help distinguish the remaining causes
I have preserved the affected thread and local logs and can provide sanitized excerpts if useful. The smallest useful instrumentation would distinguish time spent in:
turn_start_innerruns;turn_start_inner;I don't think the exact internal blocker is proven yet, but the repeatable old-thread-vs-fresh-thread A/B makes this look like a thread-scoped runtime/acceptance bug class rather than ordinary model generation latency or repository size.
gkb commentedon Sep 27, 2026
Still reproducing on a newer build — desktop 26.924.22138, codex-cli 0.158.0-alpha.2.1, macOS 27.0 (Apple Silicon).
Same symptom: "Error submitting message — timeout", and resending ~1 min later succeeds. Some numbers that line up with the SQLite-contention theory:
~/.codex/logs_2.sqliteis 2.0 GB (WAL 12 MB).codexCLI processes, and several computer-use helper processes.turn/startat 12:45:31, right after the error banner (12:45:14). That's the same "sidecar goes quiet, then recovers" pattern described above.One confound: system load was high at the time (load average ~100, from an unrelated stuck macOS service). So heavy CPU contention may make the stall more likely, but the DB size and number of processes match the original report.