jackwener/OpenCLI · error · AuthRequiredError

Xiaoe XIAOEID/b_user_token cookie missing — anonymous

Error message

Xiaoe XIAOEID/b_user_token cookie missing — anonymous

What it means

verifyXiaoeIdentity first checks the browser context for a non-empty XIAOEID or b_user_token cookie scoped to admin.xiaoe-tech.com. If neither cookie exists, the session is anonymous and the library throws AuthRequiredError so the caller can run the interactive login flow instead of scraping an unauthenticated page.

Source

Thrown at clis/xiaoe/auth.js:11

import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';
import { registerSiteAuthCommands } from '../_shared/site-auth.js';

async function hasXiaoeAdminCookie(page) {
  const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });
  return cookies.some(c => (c.name === 'XIAOEID' || c.name === 'b_user_token') && c.value);
}

async function verifyXiaoeIdentity(page) {
  if (!await hasXiaoeAdminCookie(page)) {
    throw new AuthRequiredError('xiaoe-tech.com', 'Xiaoe XIAOEID/b_user_token cookie missing — anonymous');
  }
  await page.goto('https://admin.xiaoe-tech.com/t/account/muti_index');
  await page.wait(3);
  const finalUrl = await page.evaluate(`location.href`);
  if (/login|signin|#\/wx$/.test(String(finalUrl || ''))) {
    throw new AuthRequiredError('xiaoe-tech.com', `Xiaoe admin page redirected to login: ${finalUrl}`);
  }
  const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });
  const xiaoeId = cookies.find(c => c.name === 'XIAOEID')?.value || '';
  const unionId = cookies.find(c => c.name === 'unionid')?.value || '';
  const probe = await page.evaluate(`
    (() => {
      const bodyText = document.body?.innerText || '';
      if (/微信扫码登录|手机号登录|登录小鹅通/.test(bodyText)) {
        return { isLoginPage: true };
      }
      const nick = document.querySelector('.user-name, .nickname, [class*="userName"], [class*="user-info"]')?.innerText?.trim() || '';
      return { isLoginPage: false, domNick: nick };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run the xiaoe login flow (registerSiteAuthCommands registers it) to obtain the admin cookies, then retry.
  2. Open https://admin.xiaoe-tech.com/ manually in the same browser profile and confirm you are logged in.
  3. Verify the browser profile / user-data-dir used by page is the one holding the session cookies.
  4. Check that page.getCookies targets the exact URL https://admin.xiaoe-tech.com (cookie scoping is URL-based).

Example fix

// before
await verifyXiaoeIdentity(page); // throws if anonymous
// after
if (!(await hasXiaoeAdminCookie(page))) {
  await runXiaoeLogin(page); // interactive login first
}
await verifyXiaoeIdentity(page);
Defensive patterns

Strategy: validation

Validate before calling

const cookies = await page.getCookies({ url: 'https://admin.xiaoe-tech.com' });
const authed = cookies.some(c => (c.name === 'XIAOEID' || c.name === 'b_user_token') && c.value);
if (!authed) await runXiaoeLogin(page);

Type guard

function hasXiaoeCookie(cs) {
  return Array.isArray(cs) && cs.some(c => (c.name === 'XIAOEID' || c.name === 'b_user_token') && !!c.value);
}

Try / catch

try {
  await verifyXiaoeIdentity(page);
} catch (e) {
  if (e instanceof AuthRequiredError) await runXiaoeLogin(page);
  else throw e;
}

Prevention

When it happens

Trigger: Calling verifyXiaoeIdentity (or any xiaoe command that invokes quickCheck/verify) when page.getCookies({url:'https://admin.xiaoe-tech.com'}) returns no XIAOEID and no b_user_token cookie, or both have empty values.

Common situations: Fresh browser profile that never logged into the Xiaoe admin; cookies cleared by cleanup jobs or incognito sessions; wrong cookie domain after Xiaoe changed admin domains; running headless automation on a machine that was never logged in.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/df9e7697ea752e0c. Report an issue: GitHub.