{"record":{"id":"df8e98f586e623d7","repo":"can1357/oh-my-pi","slug":"live-transport-is-not-connected","errorCode":null,"errorMessage":"Live transport is not connected","messagePattern":"Live transport is not connected","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/live/transport.ts","lineNumber":374,"sourceCode":"\n\t#handlePeerFailure(message: string): void {\n\t\tthis.#reportFailure(message);\n\t}\n\n\t#reportFailure(message: string): void {\n\t\tif ((this.#state !== \"connecting\" && this.#state !== \"connected\") || this.#unexpectedFailureReported) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#unexpectedFailureReported = true;\n\t\ttry {\n\t\t\tthis.#options.callbacks.onEvent({ type: \"error\", message });\n\t\t} catch {}\n\t}\n\n\t/** Serialize one Frameless Bidi control message onto the call's sideband WebSocket. */\n\tsend(message: LiveClientMessage): Promise<void> {\n\t\tconst operation = this.#sendTail.then(() => {\n\t\t\tif (this.#state !== \"connected\") throw new Error(\"Live transport is not connected\");\n\t\t\tconst sideband = this.#sideband;\n\t\t\tif (!sideband || sideband.readyState !== WebSocket.OPEN) {\n\t\t\t\tthrow new Error(\"Codex live sideband is not connected\");\n\t\t\t}\n\t\t\tsideband.send(JSON.stringify(message));\n\t\t});\n\t\tthis.#sendTail = operation.catch(() => {});\n\t\treturn operation;\n\t}\n\n\t/** Queue 16 kHz mono Float32 PCM for native Opus transmission. */\n\tpushAudio(samples: Float32Array): void {\n\t\tif (this.#state !== \"connected\" || this.#muted || samples.length === 0) return;\n\t\tthis.#peer?.pushAudio(samples);\n\t}\n\n\t/** Enable or disable the native audio source and discard partial input when muted. */\n\tasync setMuted(muted: boolean): Promise<void> {","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/live/transport.ts#L356-L392","documentation":"send() serializes a live client message onto the call's sideband WebSocket, but only when the transport state is \"connected\". If the transport has never connected, or was closed/failed, it refuses to enqueue the write and throws synchronously at the state check.","triggerScenarios":"Calling transport.send() before connect() resolves, after close(), or after the underlying call dropped and state transitioned away from \"connected\" (e.g. during reconnect).","commonSituations":"Sending a control message from an event handler racing a disconnect, forgetting to await connect(), or app code holding a stale transport reference after the live session ended.","solutions":["Check transport state (or a connected flag) before calling send.","Await connect() completion before sending any messages.","Reconnect the transport, then resend queued messages.","Guard sends inside try/catch and requeue on \"not connected\" errors."],"exampleFix":"// before\ntransport.send({ type: \"input\", text });\n// after\nif (transport.state === \"connected\") {\n  await transport.send({ type: \"input\", text });\n} else {\n  pendingQueue.push({ type: \"input\", text });\n}","handlingStrategy":"try-catch","validationCode":"function canSend(t: { state: string }): boolean {\n  return t.state === \"connected\";\n}\n// gate sends:\nif (canSend(transport)) await transport.send(msg); else outbox.push(msg);","typeGuard":"const isConnected = (t: { state: string }): t is { state: \"connected\" } => t.state === \"connected\";","tryCatchPattern":"try {\n  await transport.send(msg);\n} catch (e) {\n  if (e.message === \"Live transport is not connected\") {\n    outbox.push(msg);\n    await reconnectTransport();\n  } else throw e;\n}","preventionTips":["Always await connect() before sending","Track transport close events and pause producers","Queue outbound messages during reconnection windows","Avoid holding stale transport references across session restarts"],"tags":["websocket","lifecycle","state","codex","live"],"backgroundTag":"not-connected","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}