{"record":{"id":"4afde84960927729","repo":"jackwener/OpenCLI","slug":"probe-detail-4afde8","errorCode":null,"errorMessage":"${probe.detail}","messagePattern":"\\$\\{probe\\.detail\\}","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/maimai/auth.js","lineNumber":33,"sourceCode":"      if (m) { try { user = JSON.parse(m[1]); } catch {} break; }\n    }\n    if (!user || !user.id) return { kind: 'auth', detail: 'Maimai userObj missing from page (anonymous)' };\n    return {\n      ok: true,\n      user_id: String(user.id),\n      name: String(user.name || ''),\n      company: String(user.company || ''),\n    };\n  } catch (e) {\n    return { kind: 'exception', detail: String(e && e.message || e) };\n  }\n})()`;\n\nasync function verifyMaimaiIdentity(page) {\n  await page.goto('https://maimai.cn/');\n  await page.wait(2);\n  const probe = await page.evaluate(WHOAMI_PROBE);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('maimai.cn', probe.detail);\n  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from Maimai`);\n  if (probe?.kind === 'exception') throw new CommandExecutionError(`Maimai whoami failed: ${probe.detail}`);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected Maimai probe: ${JSON.stringify(probe)}`);\n  return { user_id: probe.user_id, name: probe.name, company: probe.company };\n}\n\nregisterSiteAuthCommands({\n  site: 'maimai',\n  domain: 'maimai.cn',\n  loginUrl: 'https://maimai.cn/',\n  columns: ['user_id', 'name', 'company'],\n  verify: verifyMaimaiIdentity,\n  poll: verifyMaimaiIdentity,\n});\n","sourceCodeStart":15,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/maimai/auth.js#L15-L48","documentation":"Thrown by verifyMaimaiIdentity in clis/maimai/auth.js:33 when the in-page WHOAMI_PROBE returns kind:'auth', meaning the inline userObj JSON (only injected for authenticated maimai.cn sessions) was absent. AuthRequiredError('maimai.cn', probe.detail) surfaces detail such as 'Maimai userObj missing from page (anonymous)', i.e. you are not logged in.","triggerScenarios":"Running the maimai auth check (or any cookie-strategy maimai command that verifies identity) while the shared Chrome session has no valid maimai.cn login, the session cookie expired, or the page loaded an anonymous variant missing userObj.","commonSituations":"Logged out of maimai.cn in the browser; session cookie expired after inactivity; using a fresh browser profile; maimai serving a logged-out homepage variant due to region/AB test.","solutions":["Open https://maimai.cn/ in the browser used by the CLI and log in","Re-run the verify/login command after logging in","If recently logged in, reload maimai.cn so userObj is injected, then retry","Clear stale cookies and log in again if the session is half-expired"],"exampleFix":"// before (anonymous session)\nawait verifyMaimaiIdentity(page); // throws AuthRequiredError\n// after\nawait openBrowserAndLogin('https://maimai.cn/'); // user completes login manually\nawait verifyMaimaiIdentity(page); // succeeds once userObj present","handlingStrategy":"try-catch","validationCode":"// before verifying, ensure a login cookie exists\nconst cookies = await page.getCookies({ url: 'https://maimai.cn' });\nconst hasSession = cookies.some(c => c.name.startsWith('user') || /sess|token/i.test(c.name));\nif (!hasSession) throw new Error('Log in at maimai.cn first');","typeGuard":"function isAuthError(e) {\n  return e && (e.name === 'AuthRequiredError' || /maimai\\.cn.*login|userObj missing/i.test(e.message));\n}","tryCatchPattern":"try {\n  await verifyMaimaiIdentity(page);\n} catch (e) {\n  if (isAuthError(e)) {\n    console.error('Not logged into maimai.cn — open it in the browser and log in, then retry');\n    return { needsLogin: true };\n  }\n  throw e;\n}","preventionTips":["Log into maimai.cn in the CLI's browser profile before running commands","Check session-cookie presence before batch operations","Re-login when sessions expire (maimai sessions are not permanent)","Keep the browser profile persistent so cookies survive restarts"],"tags":["authentication","browser-session","login-required"],"backgroundTag":"authentication-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}