jackwener/OpenCLI · error · CommandExecutionError

eastmoney convertible failed: HTTP ${resp.status}

Error message

eastmoney convertible failed: HTTP ${resp.status}

What it means

CommandExecutionError thrown after fetch (clis/eastmoney/convertible.js:151) when the HTTP response from push2.eastmoney.com/api/qt/clist/get has a non-2xx status (`!resp.ok`). The message embeds the status code. It wraps any server-side rejection — rate limiting, WAF block, token rejection, or upstream outage — into a single CLI-level failure.

Source

Thrown at clis/eastmoney/convertible.js:151

    const sortKey = String(args.sort ?? 'turnover').toLowerCase();
    const sort = SORTS[sortKey];
    if (!sort) throw new ArgumentError(`Unknown sort "${sortKey}". Valid: ${Object.keys(SORTS).join(', ')}`);
    const limit = parseConvertibleLimit(args.limit);

    const url = new URL('https://push2.eastmoney.com/api/qt/clist/get');
    url.searchParams.set('pn', '1');
    url.searchParams.set('pz', String(limit));
    url.searchParams.set('po', sort.order === 'desc' ? '1' : '0');
    url.searchParams.set('np', '1');
    url.searchParams.set('fltt', '2');
    url.searchParams.set('invt', '2');
    url.searchParams.set('fid', sort.fid);
    url.searchParams.set('fs', 'b:MK0354');
    url.searchParams.set('fields', 'f12,f14,f2,f3,f6,f229,f230,f232,f234,f235,f236,f237,f238,f239,f243');
    url.searchParams.set('ut', 'bd1d9ddb04089700cf9c27f6f7426281');

    const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
    if (!resp.ok) throw new CommandExecutionError(`eastmoney convertible failed: HTTP ${resp.status}`);
    let data;
    try {
      data = await resp.json();
    } catch (error) {
      throw new CommandExecutionError(`eastmoney convertible returned invalid JSON: ${error?.message ?? error}`);
    }
    const diff = extractConvertibleDiff(data);

    return mapConvertibleRows(diff, limit);
  },
});

export const __test__ = { SORTS, extractConvertibleDiff, mapConvertibleRow, mapConvertibleRows, parseConvertibleLimit };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the status in the message: 403 → token/WAF issue, 429 → back off and slow the request rate, 5xx → retry later.
  2. Retry with exponential backoff; transient 5xx/429 usually clear.
  3. Send a realistic browser User-Agent (the CLI sends 'Mozilla/5.0'; a fuller UA string helps against WAF).
  4. Check network path — disable VPN/proxy or try a residential IP if blocked.
  5. Verify the endpoint is up by curling the exact URL and inspecting status/headers.

Example fix

// before
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (!resp.ok) throw new CommandExecutionError(`eastmoney convertible failed: HTTP ${resp.status}`);
// after
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' } });
if (resp.status === 429 || resp.status >= 500) {
  await new Promise(r => setTimeout(r, 2000));
  return fetchConvertible(); // retry once with backoff
}
if (!resp.ok) throw new CommandExecutionError(`eastmoney convertible failed: HTTP ${resp.status}`);
Defensive patterns

Strategy: retry

Validate before calling

// Nothing to validate pre-call; validate status post-call:
const resp = await fetch(url);
if (resp.status === 429 || resp.status >= 500) return retryWithBackoff();
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);

Try / catch

try {
  const rows = await convertibleRows();
} catch (e) {
  const m = String(e.message).match(/HTTP (\d+)/);
  if (m) {
    const status = Number(m[1]);
    if (status === 429 || status >= 500) return retryWithBackoff(convertibleRows, 3);
    if (status === 403) console.error('blocked: rotate IP/User-Agent or refresh ut token');
  }
  throw e;
}

Prevention

When it happens

Trigger: Any fetch to the clist endpoint returning 4xx/5xx: 403 from eastmoney's WAF for suspicious IPs or missing/rotated `ut` token, 429 from request-rate limits, 5xx from push2 outages, or proxy errors surfacing as non-OK statuses.

Common situations: Running from datacenter/cloud IPs commonly blocked by eastmoney; hammering the endpoint in a loop and tripping 429; eastmoney rotating the `ut` token causing 403; corporate proxies or firewalls rejecting the request; push2 maintenance windows returning 5xx.

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/572721ecded6865d. Report an issue: GitHub.