musistudio/claude-code-router · error · Error

Chrome login import payload must be an object.

Error message

Chrome login import payload must be an object.

What it means

The IPC/HTTP import payload handler validates that the incoming JSON body is a plain object before reading cookies/localStorage arrays. Any non-object JSON (array, string, number, null, or malformed structure) is rejected early rather than crashing deeper in the import pipeline.

Source

Thrown at packages/electron/src/main/chrome-login-import.ts:441

  return `${secure ? "https" : "http"}://${host}${normalizedPath}`;
}

function cookieDomainMatches(cookieHost: string, allowedDomain: string): boolean {
  return cookieHost === allowedDomain || cookieHost.endsWith(`.${allowedDomain}`);
}

function normalizeSameSite(value: unknown): CookieSetDetails["sameSite"] | undefined {
  return value === "lax" || value === "strict" || value === "no_restriction" || value === "unspecified"
    ? value
    : undefined;
}

function readImportPayload(payload: unknown): {
  cookies: ChromeLoginImportCookie[];
  localStorage: ChromeLoginImportLocalStorage[];
} {
  if (!isRecord(payload)) {
    throw new Error("Chrome login import payload must be an object.");
  }
  const cookies = Array.isArray(payload.cookies)
    ? payload.cookies.filter(isRecord) as ChromeLoginImportCookie[]
    : [];
  const localStorage = Array.isArray(payload.localStorage)
    ? payload.localStorage.filter(isRecord) as ChromeLoginImportLocalStorage[]
    : [];
  if (cookies.length === 0 && localStorage.length === 0) {
    throw new Error("Chrome login import payload must include cookies or localStorage.");
  }
  return { cookies, localStorage };
}

function cloneJob(job: StoredChromeLoginImportJob): ChromeLoginImportJob {
  return {
    ...job,
    domains: [...job.domains],
    ...(job.result

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Ensure the request body is a JSON object: { "cookies": [...], "localStorage": [...] }
  2. If JSON may be double-encoded, JSON.parse once before sending
  3. Log the parsed typeof in a wrapper to catch serializer bugs

Example fix

// before
await post(JSON.stringify(JSON.stringify(payload)));

// after
await post(JSON.stringify({ cookies: payload.cookies ?? [], localStorage: payload.localStorage ?? [] }));
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {
  throw new TypeError('Import payload must be a JSON object');
}

Type guard

function isImportPayloadObject(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

Try / catch

try { await importPayload(raw); } catch (e) { if (e instanceof Error && e.message === 'Chrome login import payload must be an object.') { /* fix serializer, resend */ } else throw e; }

Prevention

When it happens

Trigger: POSTing a JSON body like "[...]", "null", or "\"text\"" to the import endpoint; a serializer bug on the exporter side emitting a top-level array or primitive.

Common situations: Client serializes with JSON.stringify on the wrong variable; double-encoded JSON (a JSON string of JSON); hand-crafted curl payloads missing the outer braces.

Related errors


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