jackwener/OpenCLI · error · AuthRequiredError

Xianyu /personal redirected to login: ${finalUrl}

Error message

Xianyu /personal redirected to login: ${finalUrl}

What it means

After finding identity cookies, verifyXianyuIdentity navigates to https://www.goofish.com/personal and reads the final URL. If the page was redirected to a passport.taobao.com or passport.goofish.com login/member URL, the session cookies are stale or invalid, and an AuthRequiredError is thrown including the redirect target. This catches the case where cookies exist but the server no longer accepts them as a logged-in session.

Source

Thrown at clis/xianyu/auth.js:17

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

async function hasXianyuIdentityCookie(page) {
  const cookies = await page.getCookies({ url: 'https://www.goofish.com' });
  return cookies.some(c => (c.name === 'unb' || c.name === 'tracknick') && c.value);
}

async function verifyXianyuIdentity(page) {
  if (!await hasXianyuIdentityCookie(page)) {
    throw new AuthRequiredError('goofish.com', 'Xianyu unb/tracknick cookie missing — anonymous');
  }
  await page.goto('https://www.goofish.com/personal');
  await page.wait(2);
  const finalUrl = await page.evaluate(`location.href`);
  if (/passport\.(taobao|goofish)\.com\/(member\/login|login)/.test(String(finalUrl || ''))) {
    throw new AuthRequiredError('goofish.com', `Xianyu /personal redirected to login: ${finalUrl}`);
  }
  const cookies = await page.getCookies({ url: 'https://www.goofish.com' });
  const tracknick = cookies.find(c => c.name === 'tracknick')?.value || '';
  const unb = cookies.find(c => c.name === 'unb')?.value || '';
  const probe = await page.evaluate(`
    (() => {
      const bodyText = document.body?.innerText || '';
      const requiresAuth = /请先登录|登录后/.test(bodyText);
      const blocked = /验证码|安全验证|异常访问/.test(bodyText);
      const nick = document.querySelector('.user-name, .user-nick, .nick, [class*="nickname"]')?.innerText?.trim() || '';
      const html = document.body?.innerHTML || '';
      const userIdMatch = html.match(/['"]?userId['"]?\\s*[:=]\\s*['"]?(\\d+)/i);
      return { requiresAuth, blocked, domNick: nick, domUserId: userIdMatch?.[1] || '' };
    })()
  `);
  if (probe.blocked) {
    throw new AuthRequiredError('goofish.com', 'Xianyu blocked by verification / risk control');
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the xianyu login command and log in again to refresh the session cookies.
  2. Delete stale goofish.com/taobao.com cookies in the CLI's browser profile, then log in fresh.
  3. Verify the system clock is correct (wrong time can invalidate session cookies).
  4. If it recurs quickly, check whether you are logged in on other devices/sessions that may invalidate this one.

Example fix

// before
await page.goto('https://www.goofish.com/personal');
// after
await page.goto('https://www.goofish.com/personal');
const url = await page.evaluate('location.href');
if (/passport\.(taobao|goofish)\.com/.test(url)) {
  await clearSiteCookies(page, 'goofish.com');
  await runInteractiveLogin('xianyu'); // refresh expired session
}
Defensive patterns

Strategy: try-catch

Validate before calling

const cookies = await page.getCookies({ url: 'https://www.goofish.com' });
const unb = cookies.find(c => c.name === 'unb');
// presence is necessary but not sufficient — expired sessions still redirect,
// so probe /personal and inspect the final URL before doing real work
await page.goto('https://www.goofish.com/personal');
const finalUrl = await page.evaluate('location.href');
if (/passport\.(taobao|goofish)\.com/.test(finalUrl)) await runInteractiveLogin('xianyu');

Type guard

function isLoginRedirect(url) {
  return /passport\.(taobao|goofish)\.com\/(member\/login|login)/.test(String(url || ''));
}

Try / catch

try {
  await verifyXianyuIdentity(page);
} catch (err) {
  if (/redirected to login/.test(err.message)) {
    await clearSiteCookies(page, 'goofish.com'); // drop stale session
    await runInteractiveLogin('xianyu');
  } else throw err;
}

Prevention

When it happens

Trigger: Navigating to goofish.com/personal with unb/tracknick cookies present but expired or revoked, causing a server-side redirect to a passport login page detected by the regex /passport\.(taobao|goofish)\.com\/(member\/login|login)/.

Common situations: Long-lived browser profile whose Goofish/Taobao session expired; logging out of Taobao/Goofish elsewhere invalidates the token; Taobao rotating session tokens; system clock skew making cookies appear expired.

Related errors


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