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
- Re-run the xianyu login command and log in again to refresh the session cookies.
- Delete stale goofish.com/taobao.com cookies in the CLI's browser profile, then log in fresh.
- Verify the system clock is correct (wrong time can invalidate session cookies).
- 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
- Re-login proactively when the session is old instead of waiting for expiry.
- Check clock sync (NTP) on machines running the CLI — skewed time breaks cookie validity.
- Avoid logging out of Taobao/Goofish in other sessions while the CLI profile is active.
- Validate the final URL after navigation before scraping authenticated pages.
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
- Boss redirected to login page
- NotebookLM RPC redirected to the login page
- ${probe.detail}
- Bilibili creator-center login is required: ${message}
- Bilibili creator-center login is required: ${detail}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4ec6bb1b9f7a4623.
Report an issue: GitHub.