jackwener/OpenCLI · error · EmptyResultError

No item detail was returned for the specified item_id

Error message

No item detail was returned for the specified item_id

What it means

After the xianyu item detail fetch succeeds without an `error` field, the code verifies the response actually contains a non-empty `title`. If the returned object has no title, the library concludes no real item detail came back and throws EmptyResultError('xianyu item', 'No item detail was returned for the specified item_id'). This guards against empty-shell responses that technically parsed but carry no item data.

Source

Thrown at clis/xianyu/item.js:145

        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. Confirm the item_id is correct and the listing still exists by opening https://www.goofish.com/item?id=<item_id> in a browser.
  2. Remove the item_id from your processing queue if the listing is deleted — this is a permanent empty result.
  3. Log in to www.goofish.com in the automation browser session; some listings are only returned to authenticated sessions.
  4. Retry later if you suspect soft bot-blocking (empty payload instead of an error code).
  5. Batch-validate item_ids first (skip ones that fail) rather than letting the whole run abort.

Example fix

// before: one dead item aborts the batch
for (const id of ids) await itemDetail(id);

// after: treat empty result as 'listing gone' and continue
for (const id of ids) {
  try { await itemDetail(id); }
  catch (e) { if (e instanceof EmptyResultError) { missing.push(id); continue; } throw e; }
}
Defensive patterns

Strategy: try-catch

Type guard

function hasItemPayload(r) { return r != null && typeof r.title === 'string' && r.title.trim().length > 0; }

Try / catch

try {
  await itemDetail(id);
} catch (e) {
  if (e instanceof EmptyResultError && /No item detail/.test(e.message)) {
    markListingGone(id); return null; // treat as deleted listing
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting an item_id for a listing that was deleted, is unlisted/private, is region-locked, or for which the API returns an empty/blank detail object (title missing or whitespace-only).

Common situations: Processing old item_ids from a database where listings have since been removed; scraping items outside the logged-in account's visible region; item IDs mistyped so a different (empty) entity is returned; bot-detection serving empty payloads instead of an explicit error.

Related errors


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