{"record":{"id":"f20fe34a9b951d74","repo":"jackwener/OpenCLI","slug":"xiaoe-admin-page-rendered-but-no-user-id-cookie-ex","errorCode":null,"errorMessage":"Xiaoe admin page rendered but no user_id cookie extractable — stale session","messagePattern":"Xiaoe admin page rendered but no user_id cookie extractable — stale session","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaoe/auth.js","lineNumber":37,"sourceCode":"  const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });\n  const xiaoeId = cookies.find(c => c.name === 'XIAOEID')?.value || '';\n  const unionId = cookies.find(c => c.name === 'unionid')?.value || '';\n  const probe = await page.evaluate(`\n    (() => {\n      const bodyText = document.body?.innerText || '';\n      if (/微信扫码登录|手机号登录|登录小鹅通/.test(bodyText)) {\n        return { isLoginPage: true };\n      }\n      const nick = document.querySelector('.user-name, .nickname, [class*=\"userName\"], [class*=\"user-info\"]')?.innerText?.trim() || '';\n      return { isLoginPage: false, domNick: nick };\n    })()\n  `);\n  if (probe.isLoginPage) {\n    throw new AuthRequiredError('xiaoe-tech.com', 'Xiaoe admin page showed login UI — anonymous session');\n  }\n  const userId = xiaoeId || unionId;\n  if (!userId) {\n    throw new CommandExecutionError('Xiaoe admin page rendered but no user_id cookie extractable — stale session');\n  }\n  return { user_id: String(userId), nickname: String(probe.domNick || '') };\n}\n\nregisterSiteAuthCommands({\n  site: 'xiaoe',\n  domain: 'xiaoe-tech.com',\n  loginUrl: 'https://admin.xiaoe-tech.com/',\n  columns: ['user_id', 'nickname'],\n  quickCheck: hasXiaoeAdminCookie,\n  verify: verifyXiaoeIdentity,\n  poll: async (page) => {\n    if (!await hasXiaoeAdminCookie(page)) {\n      throw new AuthRequiredError('xiaoe-tech.com', 'Waiting for Xiaoe XIAOEID/b_user_token cookie');\n    }\n    return verifyXiaoeIdentity(page);\n  },\n});","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaoe/auth.js#L19-L55","documentation":"The page rendered as authenticated (not a login UI) but neither the XIAOEID nor the unionid cookie yielded a user_id value. Since the library cannot identify the account, it throws CommandExecutionError describing a stale/partial session rather than returning empty identity.","triggerScenarios":"verifyXiaoeIdentity reaches the final identity extraction with xiaoeId and unionId both empty strings — cookies.find(...) returned undefined or empty values for XIAOEID and unionid on admin.xiaoe-tech.com.","commonSituations":"Xiaoe renamed cookies (e.g. new SSO cookie names) so XIAOEID/unionid no longer exist; b_user_token present enough to pass quickCheck but identity cookies missing; domain-scoped cookies on a subdomain not returned for the queried URL.","solutions":["Log out and log in again via the xiaoe login flow so all identity cookies are reissued.","Dump page.getCookies({url:'https://admin.xiaoe-tech.com'}) and check which cookie now carries the user id.","Update the cookie names in auth.js (XIAOEID / unionid) if Xiaoe renamed them.","Fall back to scraping the user id from the rendered account page DOM if cookies are unavailable."],"exampleFix":"// before\nconst xiaoeId = cookies.find(c => c.name === 'XIAOEID')?.value || '';\n// after\nconst xiaoeId = cookies.find(c => c.name === 'XIAOEID' || c.name === 'xet-user-id')?.value || ''; // include renamed cookie","handlingStrategy":"fallback","validationCode":"const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });\nconst userId = cookies.find(c => c.name === 'XIAOEID')?.value || cookies.find(c => c.name === 'unionid')?.value;\nif (!userId) await refreshXiaoeSession();","typeGuard":"function hasUserIdCookie(cs) {\n  return ['XIAOEID', 'unionid'].some(n => !!cs.find(c => c.name === n)?.value);\n}","tryCatchPattern":"try {\n  identity = await verifyXiaoeIdentity(page);\n} catch (e) {\n  if (/no user_id cookie/.test(e.message)) {\n    await runXiaoeLogin(page);\n    identity = await verifyXiaoeIdentity(page);\n  } else throw e;\n}","preventionTips":["Dump all admin-domain cookies periodically to detect cookie renames early.","Full re-login rather than trusting partially valid sessions.","Consider a DOM-based user-id fallback if cookies become unreliable."],"tags":["auth","cookies","stale-session","xiaoe"],"backgroundTag":"missing-auth-cookie","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}