jackwener/OpenCLI · error · CliError

FETCH_ERROR

FETCH_ERROR

Error message

Sina Finance API HTTP ${res.status}

What it means

The sinafinance news command fetches Sina Finance's 7x24 live-news API (app.cj.sina.com.cn/api/news/pc) with no auth. On any non-ok response it throws a CliError with code FETCH_ERROR, the HTTP status in the message, and a hint to check the network. It distinguishes transport-level rejection from the separate NOT_FOUND case (empty feed).

Source

Thrown at clis/sinafinance/news.js:48

    domain: 'app.cj.sina.com.cn',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'limit', type: 'int', default: 20, help: 'Max results (max 50)' },
        { name: 'type', type: 'int', default: 0, help: 'News type: 0=全部 1=A股 2=宏观 3=公司 4=数据 5=市场 6=国际 7=观点 8=央行 9=其它' },
    ],
    columns: ['id', 'time', 'content', 'views'],
    func: async (args) => {
        const limit = Math.max(1, Math.min(Number(args.limit), 50));
        const apiTag = TYPE_MAP[args.type] ?? 0;
        const params = new URLSearchParams({
            page: '1',
            size: String(limit),
            tag: String(apiTag),
        });
        const res = await fetch(`https://app.cj.sina.com.cn/api/news/pc?${params}`);
        if (!res.ok) {
            throw new CliError('FETCH_ERROR', `Sina Finance API HTTP ${res.status}`, 'Check your network connection');
        }
        const json = await res.json();
        const list = json?.result?.data?.feed?.list ?? [];
        if (!list.length) {
            throw new CliError('NOT_FOUND', 'No news found', 'Try a different type or increase limit');
        }
        return list.map((item) => ({
            id: item.id ?? '',
            time: item.create_time ?? '',
            content: stripHtml(item.rich_text ?? ''),
            views: item.view_num ?? 0,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with exponential backoff, especially for 429/5xx.
  2. Check network connectivity and any proxy/VPN that may be blocked by Sina.
  3. Keep `size` within 1–50 as the command already caps it; avoid excessive polling frequency.
  4. Try a different `type`/tag in case a specific category endpoint is failing.
  5. Wait out Sina-side maintenance and verify the endpoint is still live.

Example fix

// before
const res = await fetch(`https://app.cj.sina.com.cn/api/news/pc?${params}`);
if (!res.ok) throw new CliError('FETCH_ERROR', `Sina Finance API HTTP ${res.status}`, 'Check your network connection');
// after: single retry with backoff before failing
let res = await fetch(`https://app.cj.sina.com.cn/api/news/pc?${params}`);
if (!res.ok && (res.status === 429 || res.status >= 500)) {
  await new Promise(r => setTimeout(r, 1500));
  res = await fetch(`https://app.cj.sina.com.cn/api/news/pc?${params}`);
}
if (!res.ok) throw new CliError('FETCH_ERROR', `Sina Finance API HTTP ${res.status}`, 'Check your network connection');
Defensive patterns

Strategy: retry

Validate before calling

const limit = Math.max(1, Math.min(Number(args.limit) || 20, 50));
const type = Number.isInteger(args.type) && args.type >= 0 && args.type <= 9 ? args.type : 0;
if (!Number.isFinite(limit) || limit < 1) throw new Error('limit must be 1-50');

Try / catch

try {
  const feed = await fetchNews(limit, type);
} catch (err) {
  if (err.code === 'FETCH_ERROR') {
    const m = /HTTP (\d{3})/.exec(err.message);
    if (m && (+m[1] === 429 || +m[1] >= 500)) return retryWithBackoff(() => fetchNews(limit, type), 3);
  }
  throw err;
}

Prevention

When it happens

Trigger: fetch to https://app.cj.sina.com.cn/api/news/pc?page=1&size=N&tag=T returns 403 (WAF/blocked IP), 429 (throttled), or 5xx (Sina backend outage); also DNS/proxy failures would surface differently (network throw, not this error).

Common situations: Accessing from non-CN IPs that Sina's CDN throttles; bursts of polling requests hitting rate limits; Sina API maintenance windows; oversized `size` params triggering rejection.

Related errors


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