jackwener/OpenCLI · error · CliError
HTTP_ERROR
HTTP_ERROR
Error message
`money-flow failed: HTTP ${resp.status}` What it means
The eastmoney money-flow CLI throws CliError('HTTP_ERROR') when the push2.eastmoney.com capital-flow endpoint returns a non-OK HTTP status; the CLI skips JSON parsing since the body can't be trusted. The status code is embedded in the message to distinguish rate limiting (429/403, typical of eastmoney's WAF on unauthenticated ut-token traffic) from server-side errors (5xx).
Source
Thrown at clis/eastmoney/money-flow.js:60
'f12', 'f14', 'f2', 'f3',
range.fields.net, range.fields.netPct,
range.fields.super, range.fields.big, range.fields.medium, range.fields.small,
];
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', po);
url.searchParams.set('np', '1');
url.searchParams.set('fltt', '2');
url.searchParams.set('invt', '2');
url.searchParams.set('fid', range.fid);
url.searchParams.set('fs', A_MARKET);
url.searchParams.set('fields', fieldList.join(','));
url.searchParams.set('ut', 'b2884a393a59ad64002292a3e90d46a5');
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow 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 money-flow data');
return diff.slice(0, limit).map((it, i) => ({
rank: i + 1,
code: it.f12,
name: it.f14,
price: it.f2,
changePercent: it.f3,
mainNet: it[range.fields.net],
mainNetRatio: it[range.fields.netPct],
superNet: it[range.fields.super],
bigNet: it[range.fields.big],
mediumNet: it[range.fields.medium],
smallNet: it[range.fields.small],
}));
},View on GitHub (pinned to 49907e53dc)
Solutions
- Read the status in the message: 403/429 indicates throttling — add delays between requests and exponential backoff/retry.
- Verify the request works via curl with the same URL and User-Agent to isolate network/proxy issues from API issues.
- If consistently rejected, check whether the ut token or fs/fields parameters need updating to match the current push2 API contract.
- For 5xx, wait and retry — eastmoney outages are usually transient.
- Reduce polling frequency and cache results if you call this endpoint repeatedly.
Example fix
// before
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow failed: HTTP ${resp.status}`);
// after — honor Retry-After on 429, retry transient failures
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (resp.status === 429) {
const wait = Number(resp.headers.get('retry-after')) || 5;
await new Promise((r) => setTimeout(r, wait * 1000));
}
if (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow failed: HTTP ${resp.status}`); Defensive patterns
Strategy: retry
Validate before calling
// Reachability pre-check before hitting the data endpoint
const probe = await fetch('https://push2.eastmoney.com', { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (!probe.ok && (probe.status === 403 || probe.status === 429)) console.warn('eastmoney throttling detected; add delays before calling money-flow'); Type guard
function isCliError(e) { return e instanceof Error && 'code' in e; }
function isHttpError(e) { return isCliError(e) && e.code === 'HTTP_ERROR'; } Try / catch
async function fetchMoneyFlowWithRetry(args, attempts = 3) {
for (let i = 0; ; i++) {
try { return await runMoneyFlow(args); }
catch (err) {
const retryable = err instanceof CliError && err.code === 'HTTP_ERROR' && /HTTP (429|5\d\d)/.test(err.message);
if (!retryable || i >= attempts - 1) throw err;
await new Promise((r) => setTimeout(r, 2000 * 2 ** i)); // exponential backoff
}
}
} Prevention
- Rate-limit your own calls to push2.eastmoney.com and cache results between runs.
- Always include a realistic desktop User-Agent header.
- Retry only 429/5xx statuses; fail fast on 4xx parameter errors.
- Verify the ut token and fs/fields parameters against the current push2 API if failures become persistent.
- Add jitter to scheduled jobs so many clients don't hammer the endpoint simultaneously.
When it happens
Trigger: Any fetch of the money-flow URL whose status is not 2xx: eastmoney rate-limiting or WAF-blocking the request, the hardcoded ut token becoming invalid, fs/fields/fid parameter combinations rejected after an API change, or transient 5xx from push2.eastmoney.com.
Common situations: Polling the endpoint in a loop or from CI triggering eastmoney's anti-scraping throttle; eastmoney rotating the shared ut token so requests get rejected; corporate/proxy environments stripping the User-Agent; persistent failures after eastmoney changes the clist API contract.
Related errors
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/11035ee85a5377a7.
Report an issue: GitHub.