BloopAI/vibe-kanban · error · Error

answerResponse.message ?? "WebRTC offer response missing SDP

Error message

answerResponse.message ?? "WebRTC offer response missing SDP answer"

What it means

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.

Source

Thrown at packages/remote-web/src/shared/lib/webrtc/connection.ts:121

    const sdpOffer: SdpOffer = { sdp: offerSdp, session_id: sessionId };
    const response = await requestRelayHostApi(hostId, "/api/webrtc/offer", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(sdpOffer),
    });

    if (!response.ok) {
      pc.close();
      throw new Error(
        `WebRTC offer failed: ${response.status} ${response.statusText}`,
      );
    }

    const answerResponse: ApiResponse<SdpAnswer> = await response.json();
    if (!answerResponse.success || !answerResponse.data) {
      pc.close();
      throw new Error(
        answerResponse.message ?? "WebRTC offer response missing SDP answer",
      );
    }

    await pc.setRemoteDescription({
      type: "answer",
      sdp: answerResponse.data.sdp,
    });

    const conn = new WebRtcConnection(pc, dc, callbacks);
    await conn.waitForOpen();
    return conn;
  }

  get isConnected(): boolean {
    return this.connected && this.dataChannel.readyState === "open";
  }

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Check the server-provided answerResponse.message first — it names the actual cause.
  2. Verify the remote host is online and its relay agent is connected before calling connect().
  3. Retry the connection; transient host unavailability often resolves on a second attempt.
  4. If messages are consistently missing, capture the raw response JSON and check signaling server logs for the failing request.

Example fix

// before
if (!answerResponse.success || !answerResponse.data) { pc.close(); throw new Error(answerResponse.message ?? '...missing SDP answer'); }
// after
if (!answerResponse.success || !answerResponse.data) {
  pc.close();
  if (isRetryable(answerResponse.message)) return connect(opts, attempt + 1); // retry once
  throw new Error(answerResponse.message ?? 'WebRTC offer response missing SDP answer');
}
Defensive patterns

Strategy: try-catch

Validate before calling

const hostOnline = await isHostOnline(hostId); // gate connect() on host availability
if (!hostOnline) await waitForHostOnline(hostId, { timeoutMs: 30000 });

Type guard

function hasSdpAnswer(r: ApiResponse<SdpAnswer>): r is ApiResponse<SdpAnswer> & { data: SdpAnswer } {
  return r.success === true && r.data != null && typeof r.data === 'object';
}

Try / catch

try {
  await connect(opts);
} catch (e) {
  if (e instanceof Error && e.message !== 'WebRTC offer failed' && !e.message.startsWith('WebRTC offer failed')) {
    // missing SDP answer path: retry once, then surface answerResponse.message
    await connect(opts);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/e62b88a17b4a6405. Report an issue: GitHub.