jackwener/OpenCLI · error · AuthRequiredError

xueqiu.com

Error message

xueqiu.com

What it means

The xueqiu watchlist command calls the portfolio stock list API and expects d.data.stocks to exist. When the response is JSON but has no data.stocks field, it throws AuthRequiredError('xueqiu.com') because xueqiu typically returns an empty/error envelope ({error_code:..., error_description:...}) instead of portfolio data when the session is not authenticated to view that portfolio. The library treats a missing stocks array as an auth problem rather than an empty list.

Source

Thrown at clis/xueqiu/watchlist.js:26

    description: '获取雪球自选股/模拟组合股票列表',
    domain: 'xueqiu.com',
    browser: true,
    args: [
        {
            name: 'pid',
            default: '-1',
            help: '分组ID:-1=全部(默认) -4=模拟 -5=沪深 -6=美股 -7=港股 -10=实盘 0=持仓(通过 xueqiu groups 获取)',
        },
        { name: 'limit', type: 'int', default: 100, help: '默认 100' },
    ],
    columns: ['symbol', 'name', 'price', 'changePercent'],
    func: async (page, kwargs) => {
        await page.goto('https://xueqiu.com');
        const pid = String(kwargs.pid || '-1');
        const url = `https://stock.xueqiu.com/v5/stock/portfolio/stock/list.json?size=100&category=1&pid=${encodeURIComponent(pid)}`;
        const d = await fetchXueqiuJson(page, url);
        if (!d.data?.stocks)
            throw new AuthRequiredError('xueqiu.com');
        return (d.data.stocks || []).slice(0, kwargs.limit).map((s) => ({
            symbol: s.symbol,
            name: s.name,
            price: s.current,
            change: s.chg,
            changePercent: s.percent != null ? s.percent.toFixed(2) + '%' : null,
            volume: s.volume,
            url: 'https://xueqiu.com/S/' + s.symbol,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into xueqiu.com in the CLI browser session, then re-run the command
  2. Run `xueqiu groups` to list valid pid values and use one of them
  3. Retry with the default pid (-1) to test whether the issue is pid-specific
  4. Inspect the raw API response to confirm error_code/error_description

Example fix

// before
const d = await fetchXueqiuJson(page, url);
if (!d.data?.stocks) throw new AuthRequiredError('xueqiu.com');
// after (surface the API's own error message)
const d = await fetchXueqiuJson(page, url);
if (d.error_code) throw new Error(`xueqiu error ${d.error_code}: ${d.error_description}`);
if (!d.data?.stocks) throw new AuthRequiredError('xueqiu.com');
Defensive patterns

Strategy: validation

Validate before calling

const loggedIn = await page.evaluate(() => document.cookie.includes('xq_a_token'));
if (!loggedIn) throw new Error('Login to xueqiu.com before fetching watchlist');

Type guard

function hasStocks(d) { return d != null && d.data != null && Array.isArray(d.data.stocks); }

Try / catch

try {
  const rows = await watchlist({ pid });
} catch (e) {
  if (e instanceof AuthRequiredError) {
    return { error: 'AUTH_REQUIRED', hint: 'Log into xueqiu.com, or verify pid via xueqiu groups' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `xueqiu watchlist` (any pid) when the response envelope lacks data.stocks — session not logged in, the pid does not exist or belongs to another user, or error_code != 0 in the response body.

Common situations: Running with an expired session where the API returns 200 with an error envelope; typo'd or invalid pid group id; private portfolio not accessible to the logged-in account.

Related errors


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