can1357/oh-my-pi · error · LiveSignalingError
Codex live signaling failed (${response.status}): ${detail}
Error message
Codex live signaling failed (${response.status}): ${detail} What it means
#signalWithAccess performs the WebRTC SDP offer/answer handshake with Codex live signaling over HTTP. When the HTTP response is not ok (4xx/5xx), it raises LiveSignalingError including the status code and a bounded snippet of the error body so the underlying rejection reason is visible.
Source
Thrown at packages/coding-agent/src/live/transport.ts:224
const headers = new Headers({
...liveSessionHeaders(access, this.#options.sessionId, this.#realtimeSessionId, attestation),
Accept: "*/*",
"Content-Type": "application/json",
});
const fetchImpl = wrapFetchForProxy(fetch, LIVE_PROVIDER);
const response = await fetchImpl(SIGNALING_URL, {
method: "POST",
headers,
body: JSON.stringify({
sdp: offer,
session: buildLiveSessionPayload(this.#options.instructions, this.#options.voice),
}),
signal: this.#options.signal,
});
const responseBody = await response.text();
if (!response.ok) {
const detail = boundedErrorBody(responseBody, response.statusText);
throw new LiveSignalingError(response.status, `Codex live signaling failed (${response.status}): ${detail}`);
}
const answer = responseBody;
if (!answer.trim())
throw new LiveSignalingError(response.status, "Codex live signaling returned an empty SDP answer");
const callId = parseLiveCallId(response.headers.get("location"));
if (!callId) {
throw new LiveSignalingError(response.status, "Codex live signaling returned no valid call ID");
}
return { answer, callId, access, attestation };
}
async #connectSideband(callId: string, access: OAuthAccess, attestation: string | undefined): Promise<void> {
let failure = new Error("Codex live sideband connection failed");
for (let attempt = 0; attempt < SIDEBAND_CONNECT_ATTEMPTS; attempt++) {
try {
await this.#openSideband(callId, access, attestation);
return;
} catch (cause) {View on GitHub (pinned to 9690622007)
Solutions
- Read the status code and `detail` in the message — 401/403 means refresh OAuth credentials; 429 means back off and retry; 5xx means retry later.
- Refresh the Codex OAuth access token (re-login).
- Retry the signaling request with exponential backoff for 429/5xx.
- Verify network/proxy settings allow reaching the signaling host.
Example fix
// before
const { answer } = await transport.signal(offer); // raw LiveSignalingError
// after
try {
const { answer } = await transport.signal(offer);
} catch (e) {
if (e instanceof LiveSignalingError && (e.status === 429 || e.status >= 500)) await backoffRetry();
else if (e.status === 401) await refreshOAuthAndRetry();
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: ensure OAuth access exists and looks unexpired
if (!access?.accessToken || access.expiresAt <= Date.now() + 60_000) {
await refreshAccess();
} Type guard
const isLiveSignalingError = (e: unknown): e is LiveSignalingError => e instanceof LiveSignalingError;
Try / catch
try {
await transport.signal(offer);
} catch (e) {
if (e instanceof LiveSignalingError) {
if (e.status === 401 || e.status === 403) await refreshOAuthAndRetry();
else if (e.status === 429 || e.status >= 500) await retryWithBackoff();
else throw e;
} else throw e;
} Prevention
- Refresh OAuth tokens before long live sessions
- Add exponential backoff for 429/5xx signaling responses
- Log the status + detail snippet from the error message
- Verify proxy/network reachability to the signaling host
When it happens
Trigger: POSTing an SDP offer to the Codex live signaling endpoint and receiving a non-2xx response — expired/insufficient OAuth access, invalid offer body, missing attestation, rate limiting (429), or upstream outage (5xx).
Common situations: Expired ChatGPT/OAuth token, region or entitlement without live access, network proxy returning an error page, transient OpenAI-side 5xx during peak load.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Codex live signaling returned an empty SDP answer
- Codex live signaling returned no valid call ID
- V2 remote compaction failed (${response.status} ${response.s
- sso-role
- HTTP request failed. status=${response.status}; url=${url};
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fc3a351a100d2b02.
Report an issue: GitHub.