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

  1. Pass the real session identifier from the bot gateway session that owns the QR login flow.
  2. 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

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


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/59fa9311ef5c7838. Report an issue: GitHub.