musistudio/claude-code-router · error · Error
QR window sessionId is required.
Error message
QR window sessionId is required.
What it means
Thrown by openBotGatewayQrWindow when the sessionId in the open request is empty after trimming. The Electron main process uses sessionId to key QR login windows so repeated opens for the same session reuse the existing window; without it the window cannot be tracked or deduplicated.
Source
Thrown at packages/electron/src/main/bot-gateway-qr-window-service.ts:16
import { BrowserWindow, shell } from "electron";
import type {
BotGatewayQrWindowCloseRequest,
BotGatewayQrWindowCloseResult,
BotGatewayQrWindowOpenRequest,
BotGatewayQrWindowOpenResult
} from "@ccr/core/contracts/app";
const qrWindows = new Map<string, BrowserWindow>();
export async function openBotGatewayQrWindow(
request: BotGatewayQrWindowOpenRequest
): Promise<BotGatewayQrWindowOpenResult> {
const sessionId = request.sessionId.trim();
if (!sessionId) {
throw new Error("QR window sessionId is required.");
}
const url = parseQrWindowUrl(request.url);
const existing = qrWindows.get(sessionId);
if (existing && !existing.isDestroyed()) {
if (existing.webContents.getURL() !== url) {
await loadQrWindowUrl(existing, url, Boolean(request.waitForScan));
}
existing.show();
existing.focus();
if (request.waitForScan) {
return { opened: true, ...await waitForQrWindowClose(existing) };
}
return { opened: true };
}
const window = new BrowserWindow({
height: 760,View on GitHub (pinned to 99f24806c6)
Solutions
- Pass the real session identifier from the bot gateway session that owns the QR login flow.
- Validate/trim the sessionId before calling openBotGatewayQrWindow and surface a form error to the user if empty.
Example fix
// before
await openBotGatewayQrWindow({ sessionId: " ", url });
// after
const sessionId = session.id.trim();
if (sessionId) await openBotGatewayQrWindow({ sessionId, url }); Defensive patterns
Strategy: validation
Validate before calling
const sessionId = request.sessionId?.trim();
if (!sessionId) { /* show user-facing error */ } else { await openBotGatewayQrWindow({ ...request, sessionId }); } Type guard
function hasSessionId(r: unknown): r is BotGatewayQrWindowOpenRequest { return typeof (r as any)?.sessionId === "string" && (r as any).sessionId.trim().length > 0; } Try / catch
try { await openBotGatewayQrWindow(req); } catch (e) { if (e instanceof Error && e.message.includes("sessionId is required")) return { error: "Session id missing" }; throw e; } Prevention
- Propagate session.id from session creation into every QR window call
- Trim ids at the boundary
- Fail fast in UI when session bootstrap hasn't produced an id
When it happens
Trigger: Calling openBotGatewayQrWindow({ sessionId: "" }) or with a whitespace-only sessionId, or destructuring a request object whose sessionId field was never populated.
Common situations: The session was created upstream but its id wasn't propagated into the QR window request; a caller passes a placeholder empty string while bootstrapping.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- ${message}
- project_id and path are required to write a Claude Design fi
- ZCode profiles can only open the app; agent arguments are no
- Claude App profiles do not support agent arguments.
- Failed to open Claude App: ${spawnError}
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/59fa9311ef5c7838.
Report an issue: GitHub.