jackwener/OpenCLI · error · CliError

HTTP_ERROR

HTTP_ERROR

Error message

`eastmoney quote failed: HTTP ${resp.status}`

What it means

After building the ulist.np URL with the resolved secids, quote.js checks resp.ok and throws CliError HTTP_ERROR `eastmoney quote failed: HTTP ${status}` on any non-2xx response from push2.eastmoney.com. It surfaces the upstream status so the caller can distinguish auth/bot-blocking (403), bad parameters (4xx), and server faults (5xx).

Source

Thrown at clis/eastmoney/quote.js:82

      throw new CliError('INVALID_ARGUMENT', 'At least one symbol is required');
    }

    /** @type {string[]} */
    const secids = [];
    for (const s of raw) {
      try { secids.push(resolveSecid(s)); }
      catch (err) { throw new CliError('INVALID_ARGUMENT', `Unrecognized symbol "${s}"`); }
    }

    // Multi-stock in one call via ulist.np
    const url = new URL('https://push2.eastmoney.com/api/qt/ulist.np/get');
    url.searchParams.set('secids', secids.join(','));
    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 quote 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 quotes', `Check symbols: ${raw.join(', ')}`);

    return diff.map((it) => ({
      code: it.f12,
      name: it.f14,
      market: marketLabel(it.f13),
      price: it.f2,
      changePercent: it.f3,
      change: it.f4,
      open: it.f17,
      high: it.f15,
      low: it.f16,
      prevClose: it.f18,
      volume: it.f5,
      turnover: it.f6,
      turnoverRate: it.f8,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Wait and retry — many 403/5xx are transient or rate-limit related
  2. Read the status code: 403 → back off and reduce request rate; 5xx → eastmoney-side
  3. Add exponential backoff/retry with jitter around fetch
  4. Verify direct access: curl the same URL and compare status
  5. If 403 persists, rotate IP/User-Agent or check for eastmoney API changes (path, fields, ut token)

Example fix

// before
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0', Accept: 'application/json' } });
if (!resp.ok) throw new CliError('HTTP_ERROR', `eastmoney quote failed: HTTP ${resp.status}`);
// after
const resp = await fetchWithBackoff(url, { headers: { 'User-Agent': 'Mozilla/5.0', Accept: 'application/json' } });
if (!resp.ok) throw new CliError('HTTP_ERROR', `eastmoney quote failed: HTTP ${resp.status}`, `Status ${resp.status}; retry later or reduce polling rate`);
Defensive patterns

Strategy: retry

Validate before calling

// Preflight: cheap single-symbol probe before bulk calls
const probe = await fetch('https://push2.eastmoney.com/api/qt/ulist.np/get?secids=1.600000&fltt=2&fields=f12&ut=bd1d9ddb04089700cf9c27f6f7426281', { headers: { 'User-Agent': 'Mozilla/5.0', Accept: 'application/json' } });
if (!probe.ok) throw new Error(`eastmoney API unreachable: HTTP ${probe.status}`);

Type guard

null

Try / catch

try {
  await runQuote(args);
} catch (e) {
  if (e.code === 'HTTP_ERROR') {
    const status = Number(e.message.match(/HTTP (\d+)/)?.[1]);
    if (status === 429 || status >= 500) { await sleep(backoff()); return runQuote(args); }
    if (status === 403) console.error('Blocked by eastmoney — reduce polling rate or change network/UA.');
  } else throw e;
}

Prevention

When it happens

Trigger: Any non-2xx from the quote endpoint: 403 from eastmoney anti-scraping/rate limiting (very common when polling frequently or from datacenter IPs), 400 if the secids parameter is malformed, 5xx during eastmoney outages or heavy load.

Common situations: High-frequency quote polling triggering rate limits; corporate proxies or firewalls intercepting the request; eastmoney rotating or invalidating the hardcoded ut token; temporary eastmoney server errors during volatile market sessions.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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