[Windows][26.803.5235.0] Empty provisional realtime voice thread emits null realtimeSessionId and never reaches connected

Open 💬 5 comments Opened Aug 8, 2026 by Yaked1
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.803.41515

What subscription do you have?

Plus Subscription ($20)

What platform is your computer?

Microsoft Windows NT 10.0.29639.0 x64

What issue are you seeing?

Starting a new realtime voice chat from an empty Codex Desktop task consistently times out on Windows.
The app-server accepts thread/realtime/start, but the subsequent realtime-started event is logged with a null session ID:
realtime_session_started realtimeSessionId=null
The Desktop renderer cannot transition the pending voice launch to the connected state because its pending-session matching logic requires a non-null realtimeSessionId. The upstream WebRTC call-create request succeeds with HTTP 201, so this is not simply an upstream call-creation or quota failure.
The failure occurs when voice is started before the provisional task has received its first user message. The relevant sequence is:
thread/realtime/start accepted
thread/read attempted while the provisional thread is still empty
thread/read fails because includeTurns is unavailable before the first user message
realtime_session_started realtimeSessionId=null
Voice chat took too long to start
thread/realtime/stop
Representative sanitized logs:
2026-08-08T16:27:52.179Z info [AppServerConnection] realtime_session_started hostId=local realtimeSessionId=null threadId=019fe233-9a48-7b52-9ec6-051a4f3fa36c
2026-08-08T16:27:54.565Z info [AppServerConnection] realtime_session_started hostId=local realtimeSessionId=null threadId=019fe233-c952-7583-a84f-4eda142e87f5
Another attempt:
16:27:53.218 thread/realtime/start durationMs=119 <- accepted
16:27:53.457 thread/read durationMs=332
16:27:54.140 thread/read durationMs=227
16:27:54.565 realtime_session_started realtimeSessionId=null
16:27:58.145 Voice chat took too long to start
16:27:58.207 thread/realtime/stop durationMs=43
The associated empty-thread read failure is:
thread <redacted-thread-id> is not materialized yet;
includeTurns is unavailable before first user message
The UI error is:
Voice chat took too long to start
DeviceCheck also repeatedly reports:
DeviceCheck attestation unavailable errorCode=1
I have not assumed that the DeviceCheck error is benign. Its exact surrounding local log context still needs to be correlated with the realtime attempt.
Relevant provisional thread IDs from the failed attempts are:
019fe233-9a48-7b52-9ec6-051a4f3fa36c
019fe233-c952-7583-a84f-4eda142e87f5
No upstream realtime session ID was returned; the observed value was null.
There was no user prompt or first user message before the voice button was clicked. Token-limit and context-window usage are not applicable to the failure as observed: the launch fails during realtime startup before a normal model turn begins, and the supplied logs contain no token-usage or context-window measurement.

What steps can reproduce the bug?

Windows 11 Pro, build 10.0.29639

Codex Desktop MSIX package:
OpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g0

Bundled/pinned app-server path, with the username redacted:
C:\Users\<USER>\AppData\Local\OpenAI\Codex\bin\cfac6bda2d141e07\codex.exe

Reported app-server version:
codex-cli 0.147.0-alpha.6.5

Reported alpha source commit: 618b8e9

CODEX_HOME:
C:\Users\<USER>\.codex

Realtime transport: WebRTC

No WebSocket fallback is available in the installed runtime.

Reproduction:
Fully exit and reopen Codex Desktop.
Open a new empty task.
Do not send a user message.
Click the real Desktop voice/start-new-voice-chat button.
Observe the Desktop and app-server logs.
The request is accepted, an empty provisional-thread read occurs, and the started event is logged with realtimeSessionId=null.
The voice overlay eventually reports Voice chat took too long to start.
A protocol-level reproduction should use a real browser-generated WebRTC SDP offer rather than a hand-written SDP string:
const pc = new RTCPeerConnection();

const audioStream =
await navigator.mediaDevices.getUserMedia({ audio: true });

pc.addTrack(audioStream.getAudioTracks()[0], audioStream);
pc.createDataChannel("oai-events");

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// Send this JSON-RPC request through the authenticated app-server
// connection. Replace <thread-id> and the SDP placeholder.
const request = {
jsonrpc: "2.0",
id: 40,
method: "thread/realtime/start",
params: {
threadId: "<thread-id>",
outputModality: "audio",
realtimeSessionId: null,
transport: {
type: "webrtc",
sdp: pc.localDescription.sdp
}
}
};
The realtimeSessionId: null value in the protocol snippet represents the default-ID path described by the public app-server API. The actual Desktop raw JSON-RPC request was not captured in this report, so I am not claiming that the Desktop request definitely contained that field/value; confirming the raw request and raw notification is part of the requested investigation.
The expected server-side sequence should include:
thread/realtime/start -> {}
thread/realtime/started -> {
threadId: "...",
realtimeSessionId: "<non-null-id>"
}
thread/realtime/sdp -> {
threadId: "...",
sdp: "..."
}
The observed sequence instead contains:
thread/realtime/started -> {
threadId: "...",
realtimeSessionId: null
}
The proxy log recorded HTTP 201 for the realtime call-create request. That confirms that upstream call creation can succeed, but it does not demonstrate that Desktop receives a valid realtime session ID or reaches the connected state.

What is the expected behavior?

Starting voice from an empty task should not cause Desktop to hydrate an unmaterialized provisional thread with an invalid includeTurns read.
The provisional voice task should either materialize correctly before hydration or proceed with a valid realtime session identifier.
The real Desktop voice launch should reach this trajectory:
voice-button click
-> thread/realtime/start accepted
-> raw thread/realtime/started notification
with a non-null realtimeSessionId
-> realtimeSessionId matches the pending voice session
-> thread/realtime/sdp
-> WebRTC connected state
-> no "Voice chat took too long to start" error
The realtimeSessionId should be non-null even if it is derived from the Codex thread ID. It should not be confused with the separate rtc_... WebRTC call ID used for sideband joining.

Additional information

Public-source discrepancy
The public rust-v0.147.0 source appears to produce a non-null default session ID:
build_realtime_session_config sets the session ID to the request’s realtimeSessionId, or falls back to the thread ID.
prepare_realtime_start clones that value into requested_realtime_session_id.
The started event emits that requested value as realtime_session_id.
Relevant official source:
realtime_conversation.rs
realtime_call.rs
Official app-server realtime documentation
The WebRTC call implementation separately removes the session JSON object’s id before creating the call and extracts an rtc_... call ID from the response Location header. That rtc_... call ID is used for sideband joining and is not the same field as the app-server realtimeSessionId.
A comparison of the relevant source ranges between rust-v0.147.0-alpha.6.5 and rust-v0.147.0 did not show a relevant change in the realtime-session-ID path. The stable release notes also do not identify an explicit fix for this null-ID/provisional-thread failure:
Stable 0.147.0 release notes
Alpha 0.147.0-alpha.6.5 release
Exact public matching issue #35252
Stable has not been substituted for the Desktop-pinned runtime on this machine, so I am not claiming that stable fixes the installed behavior.
Config investigation
The public configuration parser recognizes these experimental keys:
experimental_realtime_ws_base_url = "..."
experimental_realtime_webrtc_call_base_url = "..."
Official parser source:
config_toml.rs
The source documents these as transport endpoint overrides:
experimental_realtime_ws_base_url changes the realtime WebSocket endpoint.
experimental_realtime_webrtc_call_base_url changes the WebRTC call-creation endpoint.
Neither key supplies or repairs the per-request realtimeSessionId. No supported global config or environment key was found that forces a non-null realtime session ID.
Commenting out the local openai_base_url setting did not change the failure. The upstream call-create request still succeeded with HTTP 201.
No config file was changed during this investigation.
DeviceCheck / attestation
The repeated Desktop message is:
DeviceCheck attestation unavailable errorCode=1
The official app-server documentation defines status code 1 in its own attestation envelope as a timeout:
1 = timeout
2 = request failed
3 = request canceled
4 = malformed response
See the official attestation-generation documentation.
However, it has not yet been proven that the Desktop DeviceCheck errorCode=1 line is reporting that same app-server envelope. Please confirm whether this is:
the app-server attestation status s=1;
a Desktop-specific DeviceCheck error code; or
another wrapper-level error.
The DeviceCheck error should not be assumed benign from recurrence alone. It is also not yet proven to be the cause of the null realtime session ID.
Evidence still needed from maintainers
Please confirm:
Whether the empty provisional-thread path is expected to emit thread/realtime/started with a non-null session ID.
Whether the raw JSON-RPC thread/realtime/start request contains realtimeSessionId, and what value it contains.
Whether the raw JSON-RPC thread/realtime/started notification contains null or whether the value is lost inside Desktop’s notification mapping/logging layer.
The exact Desktop/app-server release or commit that fixed issue #35252.
Whether stable rust-v0.147.0 is supported and hash-compatible with Desktop package 26.803.5235.0.
Whether the Desktop renderer should fall back to the pending voice session ID when the started notification is null, or whether app-server must always emit the ID.
Whether DeviceCheck attestation unavailable errorCode=1 maps to the documented app-server attestation status 1 = timeout.
Whether an attestation failure can affect the realtime-started notification independently of the successful HTTP 201 call-create response.
The decisive falsifying evidence would be either:
a raw JSON-RPC trace showing a valid non-null realtimeSessionId that Desktop later logs as null, which would implicate Desktop’s mapping/logging layer; or
a clean real voice-button run on the same Desktop package/runtime that reaches connected with a matching non-null realtimeSessionId, which would disprove persistence of the reported failure.

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 19 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #36343

Powered by Codex Action

Redster999 · 16 days ago

I can confirm that this still reproduces on Windows in Codex Desktop 26.803.10989.0.

Observed on August 11, 2026:

  1. Start Voice from a new empty task before sending any text.
  2. The desktop app creates a provisional task and accepts thread/realtime/start.
  3. thread/read then fails because the task is not materialized yet and includeTurns is unavailable before the first user message.
  4. The overlay reports “Voice chat took too long to start.”
  5. realtime_session_started is logged with realtimeSessionId=null, followed by stop/cleanup errors.

This does not appear to be a microphone, audio-device, account, or basic transport problem:

  • Windows microphone permission is enabled and Windows records microphone use during the attempt.
  • Audio services and devices are healthy.
  • Starting Voice in an older, valid voice-originated task succeeds and returns a non-null RTC session ID.

There is an additional routing symptom in 26.803.10989.0:

After Voice launch from a new empty task fails, the configured Voice shortcut (Alt+D) consistently resumes the same older voice-originated task, even when another task is visibly selected. The selected task remains on screen, but the blue active-Voice indicator moves to the older task. The logs confirm that the shortcut sends thread/realtime/start for that older task, and that request succeeds.

This suggests that the provisional-task failure leaves behind, or falls back to, a stale “last valid Voice task” target. The timeout/null-session bug therefore appears to remain present in the current build, with an additional wrong-task routing/fallback symptom.

First observed locally in 26.803.5235.0 on August 7–8, and still present after updating to 26.803.10989.0 on August 11. The issue predates the ChatGPT service incident reported on August 11.

Hzzz7 · 13 days ago

Update: the same failure reproduces on a newer Windows Codex Desktop package.

Environment

  • Codex Desktop package: OpenAI.Codex_26.810.6296.0
  • Desktop release reported in the startup log: 26.810.50856
  • Bundled app-server: 0.148.0-alpha.9
  • Platform: Windows 11 Pro x64, build 26200
  • Subscription/authentication: ChatGPT Plus

Reproduction and actual behavior

  1. Launch Codex Desktop.
  2. Start a new realtime Voice Chat from a newly created empty task, before sending the first text message.
  3. The voice overlay times out.
  4. The provisional task remains visible as an empty sidebar conversation, but it cannot be archived or resumed.

Sanitized log sequence from the same attempt:

thread/realtime/start accepted
thread/read -> thread is not materialized yet;
             includeTurns is unavailable before first user message
realtime_session_started realtimeSessionId=null
Voice chat took too long to start
Failed to discard provisional realtime voice thread
no rollout found for thread id ...
Failed to resume conversation

This reproduces the core sequence reported in this issue, now on 26.810.6296.0 / app-server 0.148.0-alpha.9. The session ID remains null and the provisional-thread cleanup/resume path is still broken.

Additional information

During the same failure, the Codex UI/desktop pointer became severely laggy. Switching to a wired mouse did not change the symptom, while Ctrl+Alt+Delete remained responsive. Restarting Codex restored normal pointer behavior. This may be a related overlay/window-lifecycle symptom rather than a hardware problem.

No usernames, task IDs, local paths, conversation contents, raw logs, credentials, or tokens are included.

SIMON-WORLD · 3 days ago

Additional sanitized reproduction from another Windows installation using official ChatGPT authentication:

  • Codex Desktop package previously observed: OpenAI.Codex_26.803.5235.0_x64
  • Client previously observed: 26.803.41515
  • The account uses ChatGPT/OAuth authentication and the OpenAI provider path; there is no third-party API base_url.
  • The same error occurs after fully restarting Codex, waiting for the app to warm up, opening an existing non-empty task, and clicking Voice once. Therefore this is not only an immediate cold-start workaround case.

Observed sanitized behavior:

  1. One attempt reported Voice chat took too long to start before any thread/realtime/start entry appeared.
  2. Another single user action produced two provisional voice thread/start requests within approximately 10 ms; both provisional tasks were subsequently discarded, and neither reached thread/realtime/start.
  3. Windows audio services and dictation/microphone checks were healthy in the local investigation.

This looks related to the empty/provisional Voice task lifecycle and/or client-side launch state, even when the application is already warm and an existing task is selected. Please confirm whether the fix for the null realtimeSessionId path in this issue has landed in a public Desktop build. I can provide further sanitized timing traces if useful.

SIMON-WORLD · 3 days ago

Follow-up with a newer reproduction from the same Windows machine after the previous report:

  • Current Codex Desktop: 26.814.41957
  • Bundled CLI: 0.148.0
  • Official ChatGPT/OAuth authentication; no third-party API base URL.
  • The user waited for the app to initialize, opened an existing task, and clicked Voice exactly once.

The read-only local log window around the attempt shows:

  • thread/start began at approximately 23:00:38 with dynamic_tool_count=21.
  • During provisional-thread initialization, multiple MCP/plugin services were started and the official Responses WebSocket prewarm completed.
  • The thread/start request was cancelled at approximately 23:01:41.
  • No thread/realtime/start and no realtime_session_started event appeared within that request window.

This reproduces the failure after warm-up and from an existing task, and places the failure before Realtime/WebRTC/ICE/microphone setup. It appears to be a broader provisional Voice thread/MCP lifecycle cancellation than a simple cold-start delay. Please let me know whether a public Desktop build contains a fix for this path.