{"record":{"id":"c2d8c8d677799765","repo":"jackwener/OpenCLI","slug":"v2ex-a2-session-cookie-missing-anonymous","errorCode":null,"errorMessage":"V2EX A2 session cookie missing — anonymous","messagePattern":"V2EX A2 session cookie missing — anonymous","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/v2ex/auth.js","lineNumber":12,"sourceCode":"import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { registerSiteAuthCommands } from '../_shared/site-auth.js';\n\nasync function hasV2exAuthCookie(page) {\n  // A2 is V2EX's httpOnly logged-in session cookie.\n  const cookies = await page.getCookies({ url: 'https://www.v2ex.com' });\n  return cookies.some(c => c.name === 'A2' && c.value);\n}\n\nasync function verifyV2exIdentity(page) {\n  if (!await hasV2exAuthCookie(page)) {\n    throw new AuthRequiredError('v2ex.com', 'V2EX A2 session cookie missing — anonymous');\n  }\n  await page.goto('https://www.v2ex.com/');\n  await page.wait(1);\n  const probe = await page.evaluate(`\n    (() => {\n      const link = document.querySelector('#Top a[href^=\"/member/\"]');\n      if (!link) return { kind: 'auth', detail: 'V2EX top bar has no member link — anonymous session' };\n      const href = link.getAttribute('href') || '';\n      const username = (link.innerText || href.replace('/member/', '')).trim();\n      if (!username) return { kind: 'auth', detail: 'V2EX member link present but username empty' };\n      return { ok: true, username };\n    })()\n  `);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('v2ex.com', probe.detail);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected V2EX probe: ${JSON.stringify(probe)}`);\n  return { username: probe.username };\n}\n","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/v2ex/auth.js#L1-L30","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log in to v2ex.com in the browser session the CLI uses, then re-run","Point the CLI at the browser profile that holds your V2EX session","Persist the profile/cookies so sessions survive restarts","Re-authenticate if the A2 cookie expired"],"exampleFix":"// before\nawait verifyV2exIdentity(page); // throws: A2 cookie missing\n// after\nawait loginV2ex(page); // perform login flow first\nawait verifyV2exIdentity(page); // now A2 cookie present","handlingStrategy":"try-catch","validationCode":"async function hasA2Cookie(page) {\n  const cookies = await page.getCookies({ url: 'https://www.v2ex.com' });\n  return cookies.some(c => c.name === 'A2' && c.value);\n}\nif (!await hasA2Cookie(page)) {\n  throw new Error('Log in to v2ex.com in the automation browser first');\n}","typeGuard":"function isLoggedInCookieSet(cookies) {\n  return Array.isArray(cookies) && cookies.some(c => c.name === 'A2' && Boolean(c.value));\n}","tryCatchPattern":"try {\n  await verifyV2exIdentity(page);\n} catch (e) {\n  if (e instanceof AuthRequiredError) {\n    await openLoginFlow('v2ex.com'); // interactive login\n    return verifyV2exIdentity(page);\n  }\n  throw e;\n}","preventionTips":["Log in to v2ex.com in the exact browser profile the CLI drives","Persist the browser profile so cookies survive restarts","Re-authenticate periodically; A2 sessions expire","Check cookies before long automation runs"],"tags":["auth","v2ex","session","cookie"],"backgroundTag":"missing-auth-cookie","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}