Skip to content

Voice chat fails to start: overlay 10s launch timeout races slow skills/list; session starts after timeout fires #35968

Open

Description

@YannisKiefer

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:

  1. The walker is a fully sequential async BFS paying multiple tokio::fs round trips per directory entry (file-system/src/lib.rs walk_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 with node_modules under ~/.codex/skills/), one skills/list generates ~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.
  2. effective_skill_roots_for_layer_stack runs a full uncached plugin enumeration on every call, even when forceReload=false and the per-cwd snapshot cache would hit (catalog_processor.rs), so the per-call floor stays high.
  3. The overlay calls skills/list three times per voice attempt, serialized against a ~10s launch budget.
  4. 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/start readiness on skills/list (load skills lazily in the overlay), and/or deduplicate the three calls per attempt.
  • Cache plugin skill roots between skills/list calls.
  • 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

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    skillsIssues related to skills
    app-serverIssues involving app server protocol or interfaces
    on Jul 29, 2026
  2. liege-real-estate-drones commented on Aug 22, 2026

    @liege-real-estate-drones

    Still reproducing consistently on Windows with Codex App 26.818.5229.0.

    Platform: Microsoft Windows NT 10.0.28120.0 x64

    Voice was started from a new, empty task inside an existing project, before sending any text message. The Windows microphone permission for OpenAI.Codex is set to Allow, Windows records recent microphone use, and thread/realtime/listVoices completes without an error.

    The desktop logs show the voice startup watchdog firing before the provisional thread finishes being created:

    2026-08-22T10:06:37.030Z Voice chat took too long to start
    2026-08-22T10:06:41.102Z thread/start completed (durationMs=557)
    2026-08-22T10:06:41.109Z Conversation created
    

    The same ordering occurs on another attempt:

    2026-08-22T10:07:53.147Z Voice chat took too long to start
    2026-08-22T10:07:55.389Z thread/start completed (durationMs=272)
    2026-08-22T10:07:55.403Z Conversation created
    

    Immediately before the timeout, the logs contain repeated bundled_executable_relocation_failed warnings while copying codex.exe and the cua_node runtime 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-15e4ae99782e

  3. sinadarvi commented on Sep 5, 2026

    @sinadarvi

    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

    • Desktop application: ChatGPT / Codex, bundle com.openai.codex
    • App version: 26.901.41600, build 7982
    • Embedded Chromium: 152.0.7977.64
    • macOS: 26.6, build 25G72
    • Input: USBAudio1.0 (Jieli USB audio), 48 kHz, one channel
    • Microphone permission: enabled, verified in System Settings

    Controlled comparison

    macOS Sound settings (Sound extension PID 4661) opened the USB microphone. CoreAudio reported:

    IO Stopped Context 591 after 2008064 frames.
    

    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:

    HALS_IOContext_Legacy_Impl::StartIOThread:
    got an error from starting the IO thread, Error: 0x3C
    IO Stopped Context 523 after 0 frames.
    

    A sample of Codex's audio process captured its main thread waiting in:

    AudioOutputUnitStart
    AudioDeviceStart_mac_imp
    HALC_ProxyIOContext::StartIOProc
    HALC_ProxyIOContext::_StartIO
    HALB_IOThread::StartAndWaitForState
    HALB_IOThread::_WaitForState
    HALB_Guard::WaitFor
    

    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:

    [avatar-overlay-realtime] Voice chat took too long to start
    

    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

    • Changed microphone and tested again.
    • Tested with AirPods disconnected and Mac mini Speakers as output; failure persisted.
    • Changed VPN from WireGuard to V2BOX; failure persisted.
    • Stopped Tailscale; confirmed its VPN was disconnected and its extension process absent.
    • Restarted coreaudiod; errors returned afterward.
    • Restarted the desktop app; failure persisted.
    • Rebooted the Mac; post-reboot failure persisted.

    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:

    Test Worklet frames Nonzero samples Result
    Default USB microphone, browser defaults 258,048 235,900 Nonzero audio captured
    Exact USB microphone, mono and noise suppression requested 286,720 272,842 Nonzero audio captured
    Exact USB microphone, echo cancellation/noise suppression/automatic gain disabled 258,048 0 Stream opened and worklet ran, but all samples were zero
    AirPods input, mono and noise suppression requested 258,048 249,691 Nonzero audio captured

    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-9cccbfcd12c1

    Please use this reference to correlate the in-app feedback with the diagnostic findings above.

  4. sinadarvi commented on Sep 5, 2026

    @sinadarvi

    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:

    • Both run macOS 26.6 (25G72) and ChatGPT/Codex 26.901.41600 (7982).
    • The main app executable, app.asar, and embedded Chromium framework 152.0.7977.64 have identical SHA-256 hashes on both machines.
    • The installed ParrotAudioPlugin binaries and relevant audio-service launch flags/entitlements also match.
    • The successful MacBook session and failing Mac mini attempts used the same physical AirPods, confirmed through the CoreAudio device identifiers (identifiers omitted here).
    • The MacBook recorded five realtime_session_started events followed by realtime_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.
    • On the Mac mini, TCC explicitly returned authValue=2, error=(null) for microphone access by the actual Codex audio helper, so this is not merely a Settings-toggle assumption.
    • The Mac mini's audio helper was blocked in AudioOutputUnitStart -> AudioDeviceStart_mac_imp -> HALC_ProxyIOContext::_StartIO, with an IO resume queue waiting in HALB_IOThread::StartAndWaitForState / HALB_Guard::WaitFor. CoreAudio repeatedly logged Error: 0x3C and stopped the corresponding input context after 0 frames.

    Recovery attempts:

    1. Restarted only the stuck Codex audio helper. A new helper appeared, but Voice still failed and the same CoreAudio errors recurred.
    2. Then fully quit and reopened ChatGPT/Codex. Both the main process and audio helper had new PIDs. Fresh attempts timed out, and CoreAudio 0x3C returned. 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_started events, each followed by realtime_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:

    • The original macOS account had a saved ChatGPT/com.openai.codex volume override of about 19%.
    • During failing Codex capture startup, Vorssaint registered audio tap contexts. Codex's audio helper was blocked in AudioOutputUnitStart/CoreAudio synchronization, with repeated 0x3C timeouts and zero frames.
    • Fully stopping Vorssaint allowed Voice to start in the original account without restarting Codex (realtime_session_started).
    • Reopened Vorssaint and used its Reset to 100% control for ChatGPT only. This removed the com.openai.codex entry from its saved appVolumes preferences, and CoreAudio logged an audio tap context being unregistered.
    • With Vorssaint still running, the same Codex process successfully started another Voice session, followed by realtime_session_updated.

    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.

  5. Serg2000Mr commented on Oct 3, 2026

    @Serg2000Mr

    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:

    • On Codex Desktop 26.930.2377.0, failed attempts were recorded, timings were measured, and the workaround was verified. Voice was started using the standard button in a new, empty chat, before the first text message. The system microphone-use indicator appeared during the failed attempts.
    • After updating to 26.930.3748.0, the installed application's code was inspected directly: the timeout is still 10,000 ms. No attempt was made to reproduce the voice startup failure again on this version as part of this investigation; this confirms that the timer is unchanged, rather than reporting a new failed attempt.

    Latest failed attempt, October 3, 2026; timestamps in UTC:

    00:31:28.861 config/read completed, durationMs=4998
    00:31:30.077 thread/start requested
    00:31:32.060 thread/start completed, durationMs=1980
    00:31:32.530 Starting realtime voice transport
    00:31:33.792 Voice chat took too long to start, timeoutMs=10000, cancellationOrigin=host_timeout
    00:31:35.454 thread/realtime/start completed, durationMs=2913
    00:31:37.427 realtime_session_started
    

    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.js inside app.asar), the timer value is yce=1e4. In startIfReady(), this.setLaunchTimeout(n,yce) is still called before t.start(e), so the timeout includes chat preparation. When the timeout expires, the application resets startup and triggers cancellation with the reason startup_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:

    02:05:56.090 Starting realtime voice transport
    02:05:57.936 realtime_session_started
    02:05:58.958 realtime_session_updated
    

    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.

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 appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingperformanceskillsIssues related to skills

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions