{"record":{"id":"e62b88a17b4a6405","repo":"BloopAI/vibe-kanban","slug":"answerresponse-message-webrtc-offer-response-m","errorCode":null,"errorMessage":"answerResponse.message ?? \"WebRTC offer response missing SDP answer\"","messagePattern":"answerResponse\\.message \\?\\? \"WebRTC offer response missing SDP answer\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/remote-web/src/shared/lib/webrtc/connection.ts","lineNumber":121,"sourceCode":"\n    const sdpOffer: SdpOffer = { sdp: offerSdp, session_id: sessionId };\n    const response = await requestRelayHostApi(hostId, \"/api/webrtc/offer\", {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/json\" },\n      body: JSON.stringify(sdpOffer),\n    });\n\n    if (!response.ok) {\n      pc.close();\n      throw new Error(\n        `WebRTC offer failed: ${response.status} ${response.statusText}`,\n      );\n    }\n\n    const answerResponse: ApiResponse<SdpAnswer> = await response.json();\n    if (!answerResponse.success || !answerResponse.data) {\n      pc.close();\n      throw new Error(\n        answerResponse.message ?? \"WebRTC offer response missing SDP answer\",\n      );\n    }\n\n    await pc.setRemoteDescription({\n      type: \"answer\",\n      sdp: answerResponse.data.sdp,\n    });\n\n    const conn = new WebRtcConnection(pc, dc, callbacks);\n    await conn.waitForOpen();\n    return conn;\n  }\n\n  get isConnected(): boolean {\n    return this.connected && this.dataChannel.readyState === \"open\";\n  }\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/packages/remote-web/src/shared/lib/webrtc/connection.ts#L103-L139","documentation":"The signaling HTTP request succeeded, but the JSON envelope (ApiResponse) reports success=false or carries no data — the server did not return an SDP answer. connect() closes the peer connection and surfaces the server-provided message, or this fallback message if none was given.","triggerScenarios":"connect() -> await response.json() yields { success: false } or data === undefined/null; e.g. host unreachable from the signaling server, offer rejected due to malformed SDP, or the answer could not be produced in time.","commonSituations":"Remote host offline or mid-restart when the offer was relayed; SDP produced by an incompatible browser/codecs rejected server-side; signaling server bugs returning an empty envelope; race where the host session ended between pairing and connect.","solutions":["Check the server-provided answerResponse.message first — it names the actual cause.","Verify the remote host is online and its relay agent is connected before calling connect().","Retry the connection; transient host unavailability often resolves on a second attempt.","If messages are consistently missing, capture the raw response JSON and check signaling server logs for the failing request."],"exampleFix":"// before\nif (!answerResponse.success || !answerResponse.data) { pc.close(); throw new Error(answerResponse.message ?? '...missing SDP answer'); }\n// after\nif (!answerResponse.success || !answerResponse.data) {\n  pc.close();\n  if (isRetryable(answerResponse.message)) return connect(opts, attempt + 1); // retry once\n  throw new Error(answerResponse.message ?? 'WebRTC offer response missing SDP answer');\n}","handlingStrategy":"try-catch","validationCode":"const hostOnline = await isHostOnline(hostId); // gate connect() on host availability\nif (!hostOnline) await waitForHostOnline(hostId, { timeoutMs: 30000 });","typeGuard":"function hasSdpAnswer(r: ApiResponse<SdpAnswer>): r is ApiResponse<SdpAnswer> & { data: SdpAnswer } {\n  return r.success === true && r.data != null && typeof r.data === 'object';\n}","tryCatchPattern":"try {\n  await connect(opts);\n} catch (e) {\n  if (e instanceof Error && e.message !== 'WebRTC offer failed' && !e.message.startsWith('WebRTC offer failed')) {\n    // missing SDP answer path: retry once, then surface answerResponse.message\n    await connect(opts);\n  }\n}","preventionTips":["Confirm the remote host/agent is online before sending the offer.","Retry once on empty answers — they are often transient races.","Always log the full ApiResponse JSON when success=false to capture the server message.","Keep browser and media codec expectations aligned with what the host supports."],"tags":["webrtc","sdp","signaling","api-response"],"backgroundTag":"missing-sdp-answer","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}