jackwener/OpenCLI · warning · EmptyResultError

上游 hot-board 返回空列表。

Error message

上游 hot-board 返回空列表。

What it means

This EmptyResultError is thrown by the toutiao hot-board command when the upstream Toutiao API responds successfully but yields no usable rows after mapping and filtering. The library treats a successful response with an empty list as a distinct, expected outcome rather than silently returning []. It signals that the upstream data source had nothing to serve for the hot board at this moment.

Source

Thrown at clis/toutiao/hot.js:58

        if (!resp.ok) {
            throw new CommandExecutionError(`toutiao hot-board failed: HTTP ${resp.status}`);
        }
        let payload;
        try {
            payload = await resp.json();
        } catch (error) {
            throw new CommandExecutionError(`toutiao hot-board returned malformed JSON: ${error?.message || error}`);
        }
        if (payload?.status && payload.status !== 'success') {
            throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);
        }
        if (payload?.error || payload?.message) {
            throw new CommandExecutionError(`toutiao hot-board returned error: ${payload.error || payload.message}`);
        }
        const list = Array.isArray(payload?.data) ? payload.data : [];
        const rows = list.map(mapHotRow).filter(Boolean).slice(0, limit);
        if (rows.length === 0) {
            throw new EmptyResultError('toutiao hot', '上游 hot-board 返回空列表。');
        }
        // Re-rank (1..N) after filter so ranks are dense even if upstream had nulls.
        return rows.map((row, idx) => ({ ...row, rank: idx + 1 }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command later — an empty hot board is often transient on the upstream side.
  2. Log the raw upstream payload once to verify payload.data actually contains rows; if it does not, the upstream schema may have changed and mapHotRow must be updated.
  3. Loosen any mapHotRow field requirements only if the upstream contract genuinely changed.
  4. Handle the empty case in calling code with a friendly 'no data right now' message instead of surfacing it as a hard failure.

Example fix

// before
const rows = await hotBoard();
render(rows);
// after
let rows;
try { rows = await hotBoard(); }
catch (e) {
  if (e instanceof EmptyResultError) rows = [];
  else throw e;
}
render(rows.length ? rows : [{ title: '暂无热榜数据' }]);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const rows = await hotBoard();
} catch (e) {
  if (e instanceof EmptyResultError) {
    return []; // benign empty state
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the 'toutiao hot' command when payload.data is an empty array, or when all entries are dropped by mapHotRow().filter(Boolean) (e.g. rows missing required fields), leaving rows.length === 0.

Common situations: Upstream temporarily has no hot-board data (off-peak, API deprioritizing the endpoint); upstream changed its JSON shape so mapHotRow now returns null for every row; aggressive filtering removes all rows; regional restrictions returning an empty list.

Related errors


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