Repository navigation
Voice chat fails to start: overlay 10s launch timeout races slow skills/list; session starts after timeout fires #35968
Description
Summary
Voice chat in the Codex desktop app reliably fails with "Voice chat couldn't start — Voice chat took too long to start" whenever skills/list takes more than a few seconds. The realtime session itself actually starts — but ~1s after the overlay's hard-coded 10s launch timeout (cue=1e4 in app.asar) has already fired and torn the session down.
Environment
- macOS 15.7.3 (arm64), Codex desktop build 26.721.81911, codex-cli 0.146.0-alpha.3.1
- ~190 user/plugin skills on disk (~25 plugins enabled)
What happens (from ~/Library/Logs/com.openai.codex/...)
A single voice click produces three sequential skills/list calls in the avatar overlay's startup path, each taking 4–10s inside the app-server:
13:28:01.091 Skills/list request (avatarOverlay)
13:28:08.161 response_routed method=skills/list durationMs=5857 queueWaitMs=1213
13:28:08.745 Skills/list request (again)
13:28:11.786 [avatar-overlay-realtime] Voice chat took too long to start <- 10s timeout fires
13:28:13.544 response_routed method=skills/list durationMs=4003
13:28:16.660 Skills/list request (third time)
13:28:20.399 Conversation created ... Archive requested source=realtime_voice_provisional
13:28:23.975 response_routed method=skills/list durationMs=6628
In an earlier attempt the log shows realtime_session_started at 11:10:44.210 — 0.9s after the timeout error at 11:10:43.322. The backend was ready; the UI gave up too early.
Root cause (measured)
skills/list cost is dominated by the skill-root directory walk:
- The walker is a fully sequential async BFS paying multiple
tokio::fsround trips per directory entry (file-system/src/lib.rswalk_via_directory_reads,exec-server/src/local_file_system.rs). With a large directory inside a skill root (in my case a 6,500-file git repo withnode_modulesunder~/.codex/skills/), oneskills/listgenerates ~120,000 tracing span entries and takes 4–11s. Moving that directory out of the skill root drops span count to ~35k and standalone latency to 0.4s. effective_skill_roots_for_layer_stackruns a full uncached plugin enumeration on every call, even whenforceReload=falseand the per-cwd snapshot cache would hit (catalog_processor.rs), so the per-call floor stays high.- The overlay calls
skills/listthree times per voice attempt, serialized against a ~10s launch budget. - The launch timeout is a hard-coded constant (
cue=1e4), not configurable and not tied to actual readiness.
Note: with a busy app-server (thread hydration, MCP startups, remote-control enrollment), in-app skills/list remains 4–6.6s even after the on-disk fix above, so the 10s budget is still exceeded. A standalone app-server answers the identical request in 0.4–1.5s.
Expected
- Voice startup should not be gated on a complete skills enumeration (or the launch timeout should be generous/configurable, e.g. 30–60s).
- The session that successfully started should be attached instead of discarded when the timeout races it.
Suggestions
- Don't block
thread/realtime/startreadiness onskills/list(load skills lazily in the overlay), and/or deduplicate the three calls per attempt. - Cache plugin skill roots between
skills/listcalls. - Parallelize/batch the directory walk (metadata per entry is currently awaited one-by-one).
- Make the launch timeout configurable or increase it; on timeout, check whether the session actually started before tearing down.
Related
- Realtime V3 (macOS, 0.146.0-alpha.3.1): default sideband dials wss://chatgpt.com/backend-api/codex/<call_id> and is blocked by Cloudflare (cf-mitigated: challenge) → 403 #35490 (Cloudflare 403 on realtime endpoints) — distinct issue; that one is an upstream/network block, this one is a local startup-latency race. With Realtime V3 (macOS, 0.146.0-alpha.3.1): default sideband dials wss://chatgpt.com/backend-api/codex/<call_id> and is blocked by Cloudflare (cf-mitigated: challenge) → 403 #35490 not reproducing, voice still fails purely due to this timeout.
Activity
liege-real-estate-drones commentedon Aug 22, 2026
Still reproducing consistently on Windows with Codex App 26.818.5229.0.
Platform:
Microsoft Windows NT 10.0.28120.0 x64Voice was started from a new, empty task inside an existing project, before sending any text message. The Windows microphone permission for
OpenAI.Codexis set toAllow, Windows records recent microphone use, andthread/realtime/listVoicescompletes without an error.The desktop logs show the voice startup watchdog firing before the provisional thread finishes being created:
The same ordering occurs on another attempt:
Immediately before the timeout, the logs contain repeated
bundled_executable_relocation_failedwarnings while copyingcodex.exeand thecua_noderuntime from WindowsApps into the local Codex runtime directory. This may be another source of startup delay that races the overlay watchdog.The issue also reproduced earlier on app version 26.814.5517.0, before updating to 26.818.5229.0.
Feedback ID (logs included):
no-active-thread-01a028f1-0a7d-7510-baba-15e4ae99782esinadarvi commentedon Sep 5, 2026
Adding a related macOS report with the same “Voice chat took too long to start” symptom on the latest update available to me. I have not established that this is the same slow-skills/list race: the strongest evidence in my failed attempts is a local CoreAudio capture-start stall. Please split or redirect this report if that needs a separate issue.
User impact: Voice chat sometimes works and sometimes does not. The repeated broken starts and generic timeout errors are frustrating and annoying, especially after spending time changing microphones, VPNs, restarting the app/audio service, and rebooting without a reliable fix. This makes Voice difficult to rely on in everyday work. The diagnostic attempts below failed; the intermittent successes are my broader experience, not successes captured in these tests.
Reproduction: On the macOS desktop app, open the Codex view and start a new live Voice chat. On affected attempts it waits and reports the startup timeout instead of connecting. This concerns live conversational Voice, not composer dictation. Microphone permission is enabled.
Environment
Controlled comparison
macOS Sound settings (Sound extension PID 4661) opened the USB microphone. CoreAudio reported:
The associated device was the same Jieli USB audio input. The process was verified as /System/Library/ExtensionKit/Extensions/Sound.appex/Contents/MacOS/Sound.
During that interval, Codex audio service PID 3793 repeatedly opened the same input and failed:
A sample of Codex's audio process captured its main thread waiting in:
These are audio-device startup calls; AudioOutputUnitStart is also used for capture audio units, so its name alone does not identify an output-device fault.
User-visible failure
Repeated desktop logs report:
The app lists voices and creates the local task successfully, then startup times out. No successful Voice call was captured during this diagnostic window; overall usage is intermittent as described above.
Troubleshooting already attempted
Chrome microphone comparison
A locally served diagnostic page used getUserMedia, a 48 kHz AudioContext, and an AudioWorklet to count frames and nonzero samples. It did not save, transmit, or play microphone audio. Chrome version was verified from its installed bundle as 152.0.7977.77, compared with Codex's embedded Chromium 152.0.7977.64. These are similar Chromium versions, not identical binaries or application configurations.
Each stage measured audio after getUserMedia resolved:
For both processed USB tests and the AirPods test, getSettings reported mono, 48 kHz, echoCancellation=true, noiseSuppression=true, autoGainControl=true, and voiceIsolation=false. The default and exact-USB processed tests also succeeded in the preceding run (262,144 and 286,720 frames respectively, with nonzero samples).
The zero-sample unprocessed USB result is a limitation: a clocked worklet is not itself proof of meaningful microphone capture. It does not invalidate the successful processed USB and AirPods comparisons. No claim of raw-capture success or an echo-cancellation workaround is warranted.
This strengthens the diagnosis of a Codex-specific local capture initialization problem. It does not identify the exact defect, rule out differences between Chromium patch versions, or test the remote Voice connection. The same USB device is demonstrably capable of providing nonzero audio through Chrome with Codex-like capture constraints.
A read-only system audio snapshot still showed USB input at 48 kHz mono, AirPods hardware input at 24 kHz, and AirPods output at 48 kHz stereo. Chrome's 48 kHz track setting does not establish the AirPods hardware rate; conversion can occur. No device sample rates were changed.
All test tracks and AudioContexts were closed by the diagnostic page at completion.
Interpretation and requested improvement
The comparisons strongly point to a Codex-specific local audio initialization failure in these attempts. They do not establish whether the underlying defect is in the app, its Chromium build/configuration, or macOS compatibility, and they do not prove that every intermittent failure has the same cause. Network transport was not fully validated; changing VPNs did not resolve the observed failure. The CoreAudio retry cadence should not be treated as proof of an application watchdog.
Please investigate the audio-service startup wait and provide stage-specific diagnostics (microphone permission, local capture start, task preparation, or remote transport), with bounded cleanup and a reliable retry when startup fails. A generic timeout makes it extremely difficult to tell what needs fixing.
Only sanitized diagnostic excerpts and aggregate audio counters are included. No audio recordings, transcripts, credentials, or full application logs are attached. In-app feedback has now been submitted successfully.
Feedback ID:
01a07147-1d6f-7c82-b18e-9cccbfcd12c1Please use this reference to correlate the in-app feedback with the diagnostic findings above.
sinadarvi commentedon Sep 5, 2026
Follow-up with a working-machine comparison and a fresh full-restart failure. Feedback ID:
01a07147-1d6f-7c82-b18e-9cccbfcd12c1.I tested Voice successfully on my MacBook Pro M3 Pro, on the same LAN and using the same VPN as the failing Mac mini M4. Read-only SSH inspection confirmed:
app.asar, and embedded Chromium framework 152.0.7977.64 have identical SHA-256 hashes on both machines.ParrotAudioPluginbinaries and relevant audio-service launch flags/entitlements also match.realtime_session_startedevents followed byrealtime_session_updated. One AirPods capture in its Codex audio process delivered 231,360 frames. Its audio helper's main thread was later normally idle in its run loop.authValue=2,error=(null)for microphone access by the actual Codex audio helper, so this is not merely a Settings-toggle assumption.AudioOutputUnitStart -> AudioDeviceStart_mac_imp -> HALC_ProxyIOContext::_StartIO, with an IO resume queue waiting inHALB_IOThread::StartAndWaitForState / HALB_Guard::WaitFor. CoreAudio repeatedly loggedError: 0x3Cand stopped the corresponding input context after 0 frames.Recovery attempts:
0x3Creturned. The full restart did not resolve it.The original USB-in-Chrome and macOS Sound comparisons above also remain relevant. This strengthens the evidence for a machine-specific Codex/CoreAudio startup problem despite identical app/OS builds and a working control device. It does not establish an M4-wide defect or identify the exact underlying trigger. The shared VPN is not a sufficient explanation for the observed local capture failure.
Please investigate capture startup and recovery, including why a failed start keeps leaving the audio helper waiting rather than recovering cleanly. Repeatedly restarting and changing microphones/VPNs without an actionable error is especially frustrating for an intermittent feature that sometimes works normally.
Update: Voice works in a fresh macOS account on the same Mac mini
This changes the scope of the diagnosis. I created a temporary standard macOS user on the same Mac mini M4, opened the same installed app, and tested with the same VPN and same physical AirPods. Live Voice worked.
The test-account diagnostic file confirms two
realtime_session_startedevents, each followed byrealtime_session_updated. AirPods were present as the default input and output. An earlier fresh-account attempt had no microphone connected and is excluded from the control comparison.This points toward the original macOS user's profile/session state or user-specific software/configuration; it argues against an inherent M4 limitation or a universal app/OS incompatibility. The original user remained logged in via fast user switching, so the comparison does not yet separate Codex's stored profile from macOS per-user audio state or background-software behavior. A return-to-original-account retest is pending before modifying stored settings.
The standard test account could not read the unified system log (exit 77 / Operation not permitted); its successful Voice events and microphone inventory were collected from its own app logs and system_profiler. No claim of zero system-level errors is based on that unavailable log.
Update: isolated a per-app audio mixer interaction; Voice now starts
Further same-account testing identified Vorssaint's per-app volume mixer as a likely trigger:
Same Mac mini, account, app process, VPN and AirPods. No Codex caches, permissions or profile data were reset. This points to an interaction involving the per-app volume override/audio tap, rather than the VPN or microphone hardware. It does not establish which product owns the underlying defect or why it previously worked. Longer-term stability remains untested.
Practical workaround observed: leave Vorssaint open but reset ChatGPT's mixer volume to 100%; adjust volume using the system output control instead. Feedback ID remains 01a07147-1d6f-7c82-b18e-9cccbfcd12c1.
Serg2000Mr commentedon Oct 3, 2026
I can confirm a similar race condition when starting voice chat on Windows. A workaround has been found and verified: first send one text message in a new chat for the intended topic, wait for the response, then enable voice. There is no need to use an old chat on a different topic.
Versions and scope of verification:
Latest failed attempt, October 3, 2026; timestamps in UTC:
Confirmation that the voice session had started arrived 3.635 seconds after cancellation. Reading the configuration and creating the new chat alone took about 7 seconds of the overall timeout.
In the updated version's code (
.vite/build/main-BzfMOOKJ.jsinsideapp.asar), the timer value isyce=1e4. InstartIfReady(),this.setLaunchTimeout(n,yce)is still called beforet.start(e), so the timeout includes chat preparation. When the timeout expires, the application resets startup and triggers cancellation with the reasonstartup_timeout.Verified workaround: the user created a new chat, sent a text message, waited for the response, and enabled voice. The user confirmed that voice started successfully. The logs for this attempt show:
The interval from the start of the connection to the session update was 2.868 seconds; this is the interval between log events, not a measurement from the button click. In this attempt, no new chat had to be created before connecting voice.
This failure has been recurring for a long time and prevents starting a new chat directly with voice. Please increase the timeout or make it configurable, and separate new-chat preparation from the wait for the voice connection to become ready, so that a session being successfully established is not cancelled prematurely. No persistent settings or installed code were changed during the investigation.