{"record":{"id":"5e986789ef531dd8","repo":"jackwener/OpenCLI","slug":"waiting-for-xiaoe-xiaoeid-b-user-token-cookie","errorCode":null,"errorMessage":"Waiting for Xiaoe XIAOEID/b_user_token cookie","messagePattern":"Waiting for Xiaoe XIAOEID/b_user_token cookie","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"warning","filePath":"clis/xiaoe/auth.js","lineNumber":51,"sourceCode":"    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});\n","sourceCodeStart":33,"sourceCodeEnd":56,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaoe/auth.js#L33-L56","documentation":"The poll handler, run repeatedly while waiting for the user to finish logging in, calls hasXiaoeAdminCookie and throws AuthRequiredError('Waiting for Xiaoe XIAOEID/b_user_token cookie') until the cookie appears. It is the expected signal during interactive login polling, not a fatal fault.","triggerScenarios":"Auth polling loop invokes poll(page) after the user opened the login URL, but page.getCookies({url:'https://admin.xiaoe-tech.com'}) still shows no non-empty XIAOEID or b_user_token.","commonSituations":"User has not completed the Xiaoe login/WeChat scan yet; user logged into the wrong account or a different domain (h5.xet.citv.cn instead of admin.xiaoe-tech.com); polling window too short before timeout.","solutions":["Complete the login in the opened browser window (including WeChat scan if required) and keep polling.","Ensure you log in on https://admin.xiaoe-tech.com/, not the h5 storefront.","Extend the poll timeout if login (QR scan) takes longer than the allotted window.","Verify the polling browser context is the same profile where the user is logging in."],"exampleFix":"// before\nawait waitForAuth(page, { timeoutMs: 30000 }); // too short for QR login\n// after\nawait waitForAuth(page, { timeoutMs: 120000, poll }); // allow time for WeChat QR scan","handlingStrategy":"retry","validationCode":"while (Date.now() < deadline) {\n  const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });\n  if (cookies.some(c => (c.name === 'XIAOEID' || c.name === 'b_user_token') && c.value)) break;\n  await sleep(1000);\n}","typeGuard":"const hasCookie = cs => Array.isArray(cs) && cs.some(c => (c.name === 'XIAOEID' || c.name === 'b_user_token') && !!c.value);","tryCatchPattern":"try {\n  await poll(page);\n} catch (e) {\n  if (e instanceof AuthRequiredError && /Waiting for Xiaoe/.test(e.message)) {\n    await sleep(1000); // expected during login — keep polling\n  } else throw e;\n}","preventionTips":["Treat this error as an expected polling signal, not a failure.","Set a poll timeout generous enough for WeChat QR-scan login (2+ minutes).","Prompt the user clearly to complete login on admin.xiaoe-tech.com."],"tags":["auth","polling","cookies","xiaoe"],"backgroundTag":"waiting-for-login","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}