jackwener/OpenCLI · error · EmptyResultError

errorMessage || `Xianyu item detail request failed: ${result

Error message

errorMessage || `Xianyu item detail request failed: ${result.error}`

What it means

clis/xianyu/item.js fetches a single Xianyu (Goofish) item detail via the browser automation session. When the API response contains an `error` field, the CLI throws an EmptyResultError whose message is the API's own error_message if present, otherwise a generic 'request failed' string. The library throws this because a response with an `error` field means the remote endpoint refused or failed the request, so no usable item payload exists.

Source

Thrown at clis/xianyu/item.js:142

        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. Re-run the command; transient API failures are the most common cause.
  2. Verify the item_id is a valid current listing by opening the item URL in a normal browser.
  3. Re-authenticate the browser session for www.goofish.com (the error is only shown when the error code was not a session-expiry code, but a fresh login often resolves generic FAIL_SYS errors too).
  4. Check the error_message embedded in the thrown EmptyResultError — it mirrors the upstream API error and points at the real cause (rate limit, risk control, etc.).
  5. Reduce request frequency / add delay between lookups if the upstream error indicates throttling or risk control.

Example fix

// before: raw call fails with generic API error
await cli.run(['xianyu', 'item', '--item_id', itemId]);

// after: validate input and handle empty result gracefully
if (!/^\d{6,}$/.test(itemId)) throw new Error('invalid item_id');
try {
  await cli.run(['xianyu', 'item', '--item_id', itemId]);
} catch (e) {
  if (e instanceof EmptyResultError) console.warn('API rejected item lookup:', e.message);
  else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!/^\d{6,}$/.test(String(itemId))) throw new Error(`invalid item_id: ${itemId}`);

Type guard

function isItemDetail(r) { return r != null && typeof r === 'object' && !('error' in r) && typeof r.title === 'string' && r.title.trim() !== ''; }

Try / catch

try {
  const items = await itemDetail(itemId);
} catch (e) {
  if (e instanceof EmptyResultError) {
    // e.message carries upstream error_message; log and retry/backoff
    await sleep(RETRY_MS); return itemDetail(itemId);
  }
  if (e instanceof AuthRequiredError) return reauthenticate('www.goofish.com');
  throw e;
}

Prevention

When it happens

Trigger: Calling the xianyu item detail command for an item_id where the Goofish API returns { error: ... } — e.g. API-side failure, throttling, or the mtop gateway returning a non-session business error that is not FAIL_SYS_SESSION_EXPIRED/SESSION_EXPIRED (those are routed to AuthRequiredError instead).

Common situations: Scraping deleted or region-blocked listings; Goofish API intermittently returning business errors under load; running with an incomplete session so the gateway returns a generic FAIL_SYS error not matched by the expired-session regex; stale or wrong item_id formats slipping through to the API.

Related errors


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