{"record":{"id":"3f83e81d67725755","repo":"jackwener/OpenCLI","slug":"unexpected-v2ex-probe-json-stringify-probe","errorCode":null,"errorMessage":"Unexpected V2EX probe: ${JSON.stringify(probe)}","messagePattern":"Unexpected V2EX probe: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/v2ex/auth.js","lineNumber":27,"sourceCode":"\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\nregisterSiteAuthCommands({\n  site: 'v2ex',\n  domain: 'v2ex.com',\n  loginUrl: 'https://www.v2ex.com/signin',\n  columns: ['username'],\n  quickCheck: hasV2exAuthCookie,\n  verify: verifyV2exIdentity,\n  poll: async (page) => {\n    if (!await hasV2exAuthCookie(page)) {\n      throw new AuthRequiredError('v2ex.com', 'Waiting for V2EX A2 session cookie');\n    }\n    return verifyV2exIdentity(page);\n  },\n});\n","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/v2ex/auth.js#L9-L45","documentation":"After the auth-specific check, verifyV2exIdentity throws CommandExecutionError('Unexpected V2EX probe: ...') when the in-page probe returns something that is neither {kind:'auth'} nor {ok:true}. This is a defensive guard: the probe script is only expected to produce those two shapes, so any other result (null, undefined, or an object with different keys) means the DOM probe failed or the evaluate bridge returned malformed data.","triggerScenarios":"page.evaluate returns null/undefined (script evaluation failed, navigation destroyed the page context, or the evaluate bridge returned non-JSON), or returns an object lacking both kind:'auth' and ok:true — e.g. V2EX served a challenge/error page with unexpected markup that still matched '#Top a[href^=\"/member/\"]' but with a usable username missing under a changed structure.","commonSituations":"Page navigated or was closed during evaluate; Cloudflare interstitial captured mid-load; opencli evaluate helper returned undefined for an IIFE string; V2EX layout change produced an unexpected probe result shape.","solutions":["Inspect the JSON in the message (it contains the actual probe value) to see whether the probe was null/undefined or an unexpected object.","Retry after waiting for the page to fully load (add page.wait or a readiness check before evaluate).","Ensure the browser page stays open and no navigation occurs during the probe; rerun the command.","Manually load v2ex.com in the automation browser to clear any Cloudflare challenge, then retry.","If V2EX's markup changed, update the probe script in clis/v2ex/auth.js to match the new DOM and return the expected {ok:true, username} shape."],"exampleFix":"// before\nconst probe = await page.evaluate(`(() => { ... })()`);\n// after: guard against undefined/empty DOM before probing\nawait page.goto('https://www.v2ex.com/');\nawait page.wait(2); // let top bar render\nconst probe = await page.evaluate(`(() => { ... })()`);","handlingStrategy":"type-guard","validationCode":"await page.goto('https://www.v2ex.com/');\nawait page.wait(2); // ensure top bar rendered before probing\nif (page.isClosed()) throw new Error('Page closed before V2EX identity probe');","typeGuard":"function isOkProbe(p) {\n  return !!p && typeof p === 'object' && p.ok === true && typeof p.username === 'string' && p.username.length > 0;\n}","tryCatchPattern":"const probe = await page.evaluate(probeScript);\nif (!isOkProbe(probe) && !(probe && probe.kind === 'auth')) {\n  // retry once after a wait, then fail with the JSON detail\n}","preventionTips":["Wait for page readiness (top bar rendered) before evaluating the probe script.","Avoid navigating or closing the page concurrently with the evaluate call.","Log the raw probe value on failure — the JSON in the message reveals the actual shape.","Clear Cloudflare challenges before running DOM probes against v2ex.com."],"tags":["dom-parsing","browser-automation","unexpected-state"],"backgroundTag":"unexpected-dom-probe-result","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}