jackwener/OpenCLI · error · AuthRequiredError

V2EX A2 session cookie missing — anonymous

Error message

V2EX A2 session cookie missing — anonymous

What it means

verifyV2exIdentity checks the browser session for a non-empty V2EX 'A2' cookie before probing the page for the logged-in member link. When the cookie is absent the session is anonymous, so it throws AuthRequiredError('v2ex.com', ...) telling the user to log in first.

Source

Thrown at clis/v2ex/auth.js:12

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

async function hasV2exAuthCookie(page) {
  // A2 is V2EX's httpOnly logged-in session cookie.
  const cookies = await page.getCookies({ url: 'https://www.v2ex.com' });
  return cookies.some(c => c.name === 'A2' && c.value);
}

async function verifyV2exIdentity(page) {
  if (!await hasV2exAuthCookie(page)) {
    throw new AuthRequiredError('v2ex.com', 'V2EX A2 session cookie missing — anonymous');
  }
  await page.goto('https://www.v2ex.com/');
  await page.wait(1);
  const probe = await page.evaluate(`
    (() => {
      const link = document.querySelector('#Top a[href^="/member/"]');
      if (!link) return { kind: 'auth', detail: 'V2EX top bar has no member link — anonymous session' };
      const href = link.getAttribute('href') || '';
      const username = (link.innerText || href.replace('/member/', '')).trim();
      if (!username) return { kind: 'auth', detail: 'V2EX member link present but username empty' };
      return { ok: true, username };
    })()
  `);
  if (probe?.kind === 'auth') throw new AuthRequiredError('v2ex.com', probe.detail);
  if (!probe?.ok) throw new CommandExecutionError(`Unexpected V2EX probe: ${JSON.stringify(probe)}`);
  return { username: probe.username };
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log in to v2ex.com in the browser session the CLI uses, then re-run
  2. Point the CLI at the browser profile that holds your V2EX session
  3. Persist the profile/cookies so sessions survive restarts
  4. Re-authenticate if the A2 cookie expired

Example fix

// before
await verifyV2exIdentity(page); // throws: A2 cookie missing
// after
await loginV2ex(page); // perform login flow first
await verifyV2exIdentity(page); // now A2 cookie present
Defensive patterns

Strategy: try-catch

Validate before calling

async function hasA2Cookie(page) {
  const cookies = await page.getCookies({ url: 'https://www.v2ex.com' });
  return cookies.some(c => c.name === 'A2' && c.value);
}
if (!await hasA2Cookie(page)) {
  throw new Error('Log in to v2ex.com in the automation browser first');
}

Type guard

function isLoggedInCookieSet(cookies) {
  return Array.isArray(cookies) && cookies.some(c => c.name === 'A2' && Boolean(c.value));
}

Try / catch

try {
  await verifyV2exIdentity(page);
} catch (e) {
  if (e instanceof AuthRequiredError) {
    await openLoginFlow('v2ex.com'); // interactive login
    return verifyV2exIdentity(page);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running any v2ex command when the browser profile has no A2 cookie: never logged in to v2ex.com in the automation browser, cookies cleared/expired, or the browser launched with a fresh profile.

Common situations: Cookie expiry after V2EX rotates sessions; using a container/headless profile that never logged in; clearing cookies between runs; logging into a different V2EX account in another profile than the one the CLI uses.

Related errors


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