jackwener/OpenCLI · error · CliError

HTTP_ERROR

HTTP_ERROR

Error message

eastmoney index-board failed: HTTP ${resp.status}

What it means

This CliError with code HTTP_ERROR is thrown when the Eastmoney push2 ulist.np/get endpoint responds with a non-2xx HTTP status. The library checks resp.ok after fetching index quotes and surfaces the upstream status code in the message. It indicates a transport/response problem, not a data problem.

Source

Thrown at clis/eastmoney/index-board.js:71

    /** @type {[string,string][]} */
    let entries;
    if (group === 'all') {
      entries = [...INDEX_GROUPS.main, ...INDEX_GROUPS.hk, ...INDEX_GROUPS.us];
    } else if (INDEX_GROUPS[group]) {
      entries = INDEX_GROUPS[group];
    } else {
      throw new CliError('INVALID_ARGUMENT', `Unknown group "${group}". Valid: main, hk, us, all`);
    }

    const secids = entries.map(([secid]) => secid).join(',');
    const url = new URL('https://push2.eastmoney.com/api/qt/ulist.np/get');
    url.searchParams.set('secids', secids);
    url.searchParams.set('fltt', '2');
    url.searchParams.set('fields', FIELDS);
    url.searchParams.set('ut', 'bd1d9ddb04089700cf9c27f6f7426281');

    const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0', Accept: 'application/json' } });
    if (!resp.ok) throw new CliError('HTTP_ERROR', `eastmoney index-board failed: HTTP ${resp.status}`);
    const data = await resp.json();
    const diff = Array.isArray(data?.data?.diff) ? data.data.diff : [];
    if (diff.length === 0) throw new CliError('NO_DATA', 'eastmoney returned no index data');

    // Preserve the order defined in INDEX_GROUPS regardless of API ordering
    const byCode = new Map(diff.map((it) => [String(it.f12), it]));
    return entries
      .map(([secid, fallbackName]) => {
        const code = secid.split('.')[1];
        const it = byCode.get(code);
        if (!it) return null;
        return {
          code,
          name: it.f14 || fallbackName,
          price: it.f2,
          changePercent: it.f3,
          change: it.f4,
          open: it.f17,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with exponential backoff, since 5xx and 429 are often transient
  2. Slow down request frequency and add jitter to avoid rate limiting/bot detection
  3. Verify the secids parameter is a well-formed comma list like 1.000001,0.399001 (a malformed list can trigger 400)
  4. Test the exact URL in a browser or curl with the same User-Agent; if blocked, try a different network/IP
  5. Check Eastmoney service status; if the endpoint changed, update the API path/params

Example fix

// before
const resp = await fetch(url); // one shot, throws HTTP_ERROR on 429/5xx
// after
for (let i = 0; i < 3; i++) {
  try { return await fetchBoard(); }
  catch (e) { if (e.code === 'HTTP_ERROR' && i < 2) { await sleep(2 ** i * 500); continue; } throw e; }
}
Defensive patterns

Strategy: retry

Validate before calling

function validateSecids(entries) {
  const list = entries.map((e) => String(e[0]));
  if (list.some((s) => !/^[01]\.\d{6}$/.test(s))) {
    throw new Error('Malformed secids; expected e.g. 1.000001,0.399001');
  }
  return list.join(',');
}

Try / catch

try {
  const board = await getIndexBoard({ group: 'main' });
} catch (err) {
  if (err.code === 'HTTP_ERROR') {
    if (err.message.includes('HTTP 429') || /HTTP 5\d\d/.test(err.message)) {
      return retryWithBackoff(() => getIndexBoard({ group: 'main' }), 3);
    }
    throw err; // non-retryable 4xx
  }
  throw err;
}

Prevention

When it happens

Trigger: Eastmoney returning 4xx/5xx for the ulist.np/get request: rate limiting or bot detection (429/403) due to missing/rejected User-Agent, temporary server errors (5xx), CDN/WAF blocking the client IP, or a malformed secids parameter causing a 400.

Common situations: Bulk-polling index boards and getting throttled by Eastmoney's anti-scraping layer; running from datacenter IPs that are blocked; Eastmoney API changes or outages; corporate proxy stripping the User-Agent header.

Related errors


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