{"record":{"id":"522e1981d08cfc29","repo":"can1357/oh-my-pi","slug":"codex-live-signaling-returned-no-valid-call-id","errorCode":null,"errorMessage":"Codex live signaling returned no valid call ID","messagePattern":"Codex live signaling returned no valid call ID","errorType":"exception","errorClass":"LiveSignalingError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/live/transport.ts","lineNumber":231,"sourceCode":"\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tsdp: offer,\n\t\t\t\tsession: buildLiveSessionPayload(this.#options.instructions, this.#options.voice),\n\t\t\t}),\n\t\t\tsignal: this.#options.signal,\n\t\t});\n\t\tconst responseBody = await response.text();\n\t\tif (!response.ok) {\n\t\t\tconst detail = boundedErrorBody(responseBody, response.statusText);\n\t\t\tthrow new LiveSignalingError(response.status, `Codex live signaling failed (${response.status}): ${detail}`);\n\t\t}\n\t\tconst answer = responseBody;\n\t\tif (!answer.trim())\n\t\t\tthrow new LiveSignalingError(response.status, \"Codex live signaling returned an empty SDP answer\");\n\t\tconst callId = parseLiveCallId(response.headers.get(\"location\"));\n\t\tif (!callId) {\n\t\t\tthrow new LiveSignalingError(response.status, \"Codex live signaling returned no valid call ID\");\n\t\t}\n\t\treturn { answer, callId, access, attestation };\n\t}\n\n\tasync #connectSideband(callId: string, access: OAuthAccess, attestation: string | undefined): Promise<void> {\n\t\tlet failure = new Error(\"Codex live sideband connection failed\");\n\t\tfor (let attempt = 0; attempt < SIDEBAND_CONNECT_ATTEMPTS; attempt++) {\n\t\t\ttry {\n\t\t\t\tawait this.#openSideband(callId, access, attestation);\n\t\t\t\treturn;\n\t\t\t} catch (cause) {\n\t\t\t\tfailure = cause instanceof Error ? cause : new Error(String(cause));\n\t\t\t\tif (this.#options.signal?.aborted) throw abortReason(this.#options.signal);\n\t\t\t\tif (attempt + 1 < SIDEBAND_CONNECT_ATTEMPTS) await Bun.sleep(200 * 2 ** attempt);\n\t\t\t}\n\t\t}\n\t\tthrow failure;\n\t}","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/live/transport.ts#L213-L249","documentation":"The signaling response must include a `Location` header containing a valid call ID (parsed by parseLiveCallId). If the header is missing or the ID doesn't match the expected format, the transport cannot address the call on the sideband channel and throws LiveSignalingError.","triggerScenarios":"Signaling server returns 2xx with an SDP answer but no `location` header, a relative/malformed URL, or a call ID in an unexpected format (service version change).","commonSituations":"Codex live API contract change, misconfigured gateway dropping headers, older signaling backend that locates call IDs differently.","solutions":["Log all response headers to confirm what the server returned.","Update the client to the latest version so parseLiveCallId matches the current header format.","Retry — if a gateway intermittently strips headers, retrying may succeed.","Verify no proxy strips or rewrites the Location header."],"exampleFix":"// before\nconst { answer, callId } = await transport.signal(offer); // throws\n// after\ntry {\n  const { answer, callId } = await transport.signal(offer);\n} catch (e) {\n  if (e instanceof LiveSignalingError && e.message.includes(\"call ID\")) {\n    logger.warn(\"signaling missing call id; upgrading client may help\");\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// validate the Location header yourself after a raw signaling call if reimplementing\nconst loc = response.headers.get(\"location\");\nconst callId = loc?.match(/([0-9a-f-]{16,})/i)?.[1];\nif (!callId) throw new Error(`signaling response missing call id; location=${loc}`);","typeGuard":"const hasCallId = (r: { headers: Headers }): r is { headers: Headers } & { callId: string } =>\n  Boolean(r.headers.get(\"location\"));","tryCatchPattern":"try {\n  const { answer, callId } = await transport.signal(offer);\n} catch (e) {\n  if (e instanceof LiveSignalingError && e.message.includes(\"no valid call ID\")) {\n    logger.error(\"signaling contract mismatch; check client version and proxies\", {});\n  }\n  throw e;\n}","preventionTips":["Keep the client updated with Codex live API changes","Ensure proxies/gateways don't strip the Location header","Log full response headers on signaling failures"],"tags":["network","webrtc","signaling","codex","http-headers"],"backgroundTag":"missing-response-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}