jackwener/OpenCLI · error · AuthRequiredError

Kimi access_token cookie missing

Error message

Kimi access_token cookie missing

What it means

verifyKimiIdentity reads cookies via CDP page.getCookies for https://www.kimi.com and looks for the `access_token` cookie, which is the session credential for Kimi's API (this works even though the cookie is httpOnly). If no such cookie exists, it throws AuthRequiredError: there is no logged-in Kimi session to authenticate API calls with.

Source

Thrown at clis/kimi/auth.js:16

import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';
import { registerSiteAuthCommands } from '../_shared/site-auth.js';

async function hasKimiSessionCookie(page) {
  const cookies = await page.getCookies({ url: 'https://www.kimi.com' });
  const names = new Set(cookies.map(c => c.name));
  return names.has('access_token') || names.has('refresh_token');
}

async function verifyKimiIdentity(page) {
  // Source the token via CDP getCookies (works even if access_token is httpOnly,
  // which document.cookie cannot read).
  const cookies = await page.getCookies({ url: 'https://www.kimi.com' });
  const token = cookies.find(c => c.name === 'access_token')?.value || '';
  if (!token) {
    throw new AuthRequiredError('kimi.com', 'Kimi access_token cookie missing');
  }
  await page.goto('https://www.kimi.com/');
  await page.wait(3);
  const result = await page.evaluate(`(async () => {
    try {
      const token = ${JSON.stringify(token)};
      const res = await fetch('/api/user', { credentials: 'include', headers: { 'Authorization': 'Bearer ' + token, 'Accept': 'application/json' } });
      if (res.status === 401 || res.status === 403) {
        return { kind: 'auth', detail: 'Kimi /api/user HTTP ' + res.status };
      }
      if (!res.ok) return { kind: 'http', httpStatus: res.status };
      const d = await res.json();
      if (!d || !d.id) {
        return { kind: 'auth', detail: 'Kimi /api/user returned no id — anonymous' };
      }
      return { ok: true, user_id: String(d.id), name: String(d.name || '') };
    } catch (e) {
      return { kind: 'exception', detail: String(e && e.message || e) };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run the Kimi login flow (registerSiteAuthCommands `login` for site `kimi`) and complete the login in the browser window
  2. Confirm the cookie exists: check `access_token` for https://www.kimi.com via devtools Application > Cookies
  3. Use a persistent browser profile so cookies survive between runs
  4. Re-run after logging in again if Kimi invalidated the old session

Example fix

// before
await runKimiCommand('whoami'); // throws: access_token cookie missing
// after
if (!await hasKimiSessionCookie(page)) {
  await runKimiCommand('login'); // interactive login first
}
await runKimiCommand('whoami');
Defensive patterns

Strategy: validation

Validate before calling

const cookies = await page.getCookies({ url: 'https://www.kimi.com' });
if (!cookies.some(c => c.name === 'access_token' && c.value)) {
  throw new Error('Run `kimi login` first — no access_token cookie');
}

Type guard

function hasKimiToken(cookies) {
  return Array.isArray(cookies) && cookies.some(
    c => c && c.name === 'access_token' && typeof c.value === 'string' && c.value.length > 0
  );
}

Try / catch

try {
  await kimiWhoami();
} catch (e) {
  if (e instanceof AuthRequiredError || /access_token cookie missing/.test(e.message)) {
    await kimiLogin(); // interactive login, then retry
    await kimiWhoami();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any kimi command (or the auth verify/quick check flow) while the browser profile has no `access_token` cookie for kimi.com — i.e. never logged in, logged out, or cookies were cleared.

Common situations: Fresh browser profile used before running `kimi login`; cookies wiped by clearing browsing data or using an incognito/temporary profile; Kimi renamed or expired the cookie; a proxy or region block prevented the login page from setting the cookie.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/76abf11988db7164. Report an issue: GitHub.