jackwener/OpenCLI · error · EmptyResultError

闲鱼商品详情接口未返回有效数据

Error message

闲鱼商品详情接口未返回有效数据

What it means

After the mtop item-detail call, if the result is null/undefined or not an object, the library throws EmptyResultError('xianyu item', '闲鱼商品详情接口未返回有效数据'). This means page.evaluate did not return a usable payload at all — the in-page fetch either never completed properly or returned nothing structured. It precedes the error_code checks, so it indicates a missing/invalid response shape rather than an API error payload.

Source

Thrown at clis/xianyu/item.js:134

        { name: 'item_id', required: true, positional: true, help: '闲鱼商品 item_id' },
    ],
    columns: ['item_id', 'title', 'price', 'condition', 'brand', 'location', 'seller_name', 'want_count'],
    func: async (page, kwargs) => {
        const itemId = normalizeNumericId(kwargs.item_id, 'item_id', '1040754408976');
        await page.goto(buildItemUrl(itemId));
        await page.wait(2);
        const result = await page.evaluate(buildFetchItemEvaluate(itemId));
        if (result?.error === 'auth-required') {
            throw new AuthRequiredError('www.goofish.com', 'Xianyu item detail requires a logged-in browser session');
        }
        if (result?.error === 'blocked') {
            throw new EmptyResultError('xianyu item', 'Xianyu item detail is blocked by verification or risk control');
        }
        if (result?.error === 'mtop-not-ready') {
            throw selectorError('window.lib.mtop', '闲鱼页面未完成初始化,无法调用商品详情接口');
        }
        if (!result || typeof result !== 'object') {
            throw new EmptyResultError('xianyu item', '闲鱼商品详情接口未返回有效数据');
        }
        const errorCode = String(result.error_code || '');
        const errorMessage = String(result.error_message || '');
        if (/FAIL_SYS_SESSION_EXPIRED|SESSION_EXPIRED|FAIL_SYS/.test(errorCode) || /FAIL_SYS_SESSION_EXPIRED|SESSION_EXPIRED/.test(errorMessage)) {
            throw new AuthRequiredError('www.goofish.com', 'Xianyu item detail requires a logged-in browser session');
        }
        if (result.error) {
            throw new EmptyResultError('xianyu item', errorMessage || `Xianyu item detail request failed: ${result.error}`);
        }
        if (!String(result.title || '').trim()) {
            throw new EmptyResultError('xianyu item', 'No item detail was returned for the specified item_id');
        }
        return [result];
    },
});
export const __test__ = {
    normalizeNumericId,
    buildItemUrl,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — transient page-load timing is the usual cause.
  2. Increase the settle wait so the mtop library finishes initializing before evaluate runs.
  3. If it reproduces, check whether goofish.com changed its page/bootstrap structure and update the evaluate script.
  4. Catch code 'EMPTY_RESULT' and distinguish this hint from genuine 'no data' cases before alerting.

Example fix

// before
await page.goto(buildItemUrl(itemId));
await page.wait(2);
const result = await page.evaluate(buildFetchItemEvaluate(itemId)); // returns undefined if lib not ready
// after
await page.goto(buildItemUrl(itemId));
await page.waitForSelector('body');
await page.waitForFunction('typeof window.lib !== "undefined" && window.lib.mtop'); // ensure mtop ready
const result = await page.evaluate(buildFetchItemEvaluate(itemId));
Defensive patterns

Strategy: retry

Validate before calling

// Ensure page readiness before evaluate (in adapter code):
await page.waitForFunction('typeof window.lib !== "undefined" && window.lib.mtop');

Type guard

function isValidItemPayload(result) {
  return result !== null && typeof result === 'object' &&
    ('title' in result || 'error' in result || 'error_code' in result);
}

Try / catch

let attempt = 0;
while (attempt < 3) {
  try {
    return await cli.run(['xianyu', 'item', '--item-id', itemId]);
  } catch (err) {
    const transient = err.code === 'EMPTY_RESULT' &&
      typeof err.hint === 'string' && err.hint.includes('未返回有效数据');
    if (!transient || ++attempt >= 3) throw err;
    await sleep(2000 * attempt);
  }
}

Prevention

When it happens

Trigger: Running `xianyu item --item-id <id>` when `page.evaluate(buildFetchItemEvaluate(itemId))` resolves to null, undefined, a primitive, or otherwise a non-object — no `{ error, error_code, title, ... }` payload came back.

Common situations: Page didn't finish initializing before evaluate ran (the 2s wait was insufficient); mtop lib (window.lib.mtop) loaded but returned nothing; page navigated or was replaced mid-evaluation; network hiccup swallowed the response.

Related errors


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