BloopAI/vibe-kanban · error
(dynamic: extractErrorMessage(response, fallbackMessage))
Error message
(dynamic: extractErrorMessage(response, fallbackMessage))
What it means
parseLocalApiResponse throws Error(extractErrorMessage(response, fallbackMessage)) when the local/relay session API responds with a non-2xx status. The message is dynamic: it prefers the JSON body's `message` or `error` field, else falls back to the caller's fallback string with the HTTP status appended.
Source
Thrown at packages/web-core/src/shared/lib/relayBackendApi.ts:199
interface LocalApiSuccess<T> {
success: true;
data: T;
}
interface LocalApiFailure {
success: false;
message?: string;
}
type LocalApiEnvelope<T> = LocalApiSuccess<T> | LocalApiFailure;
async function parseLocalApiResponse<T>(
response: Response,
fallbackMessage: string
): Promise<T> {
if (!response.ok) {
throw new Error(await extractErrorMessage(response, fallbackMessage));
}
const body = (await response.json()) as LocalApiEnvelope<T>;
if (!body.success) {
throw new Error(body.message || fallbackMessage);
}
return body.data;
}
async function extractErrorMessage(
response: Response,
fallbackMessage: string
): Promise<string> {
try {
const body = await response.json();
if (body && typeof body.message === 'string') {
return body.message;View on GitHub (pinned to 4deb7eca8f)
Solutions
- Log response.status and the extracted body message to identify the server-side cause.
- Verify hostId and browser sessionId are valid and the relay session is still alive before retrying.
- Check frontend/backend version alignment for the StartSpake2/FinishSpake2 request shapes.
- Surface the message to the user and restart the pairing flow from scratch (PAKE state is single-use).
Example fix
// before
const res = await startRelaySpake2Enrollment(hostId, sessionId, payload);
// after
let res;
try {
res = await startRelaySpake2Enrollment(hostId, sessionId, payload);
} catch (e) {
showToast(e.message); // server-provided message or 'Failed to start pairing. (400)'
restartPairingFlow();
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate inputs the server checks
if (!hostId || !sessionId) throw new Error('hostId/sessionId required');
if (!payload) throw new Error('payload required'); Type guard
function isHttpError(e: unknown, statusHint?: number): e is Error {
return e instanceof Error && (statusHint === undefined || /\(\d{3}\)/.test(e.message));
} Try / catch
try {
const res = await startRelaySpake2Enrollment(hostId, sessionId, payload);
} catch (e) {
if (e instanceof Error) {
showToast(e.message); // server message or 'Failed to start pairing. (NNN)'
restartPairing();
}
} Prevention
- Verify hostId/sessionId are valid before building the relay URL
- Keep frontend/backend request schema versions in sync
- Treat PAKE sessions as single-use: restart from start on any failure
- Log response status alongside the error for diagnosis
When it happens
Trigger: startRelaySpake2Enrollment, finishRelaySpake2Enrollment, or refreshRelaySigningSession gets a non-ok Response (e.g. 400 bad PAKE payload, 404 wrong host/session, 409 pairing state mismatch, 500 server error) from /api/relay-auth/... endpoints.
Common situations: Server rejects the SPAKE2 flow mid-pairing; wrong hostId/sessionId in the relay URL; server not running the relay-auth endpoints (404); request body schema drift between frontend and backend versions.
Related errors
- body.message || fallbackMessage (dynamic)
- This host is not paired with your browser. Pair it in Relay
- This host pairing is outdated. Re-pair it in Relay settings.
- answerResponse.message ?? "WebRTC offer response missing SDP
- Server proof verification failed.
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/b3ced83049e4891b.
Report an issue: GitHub.