{"record":{"id":"11035ee85a5377a7","repo":"jackwener/OpenCLI","slug":"http-error-11035e","errorCode":"HTTP_ERROR","errorMessage":"`money-flow failed: HTTP ${resp.status}`","messagePattern":"`money-flow failed: HTTP (.+?)`","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/eastmoney/money-flow.js","lineNumber":60,"sourceCode":"      'f12', 'f14', 'f2', 'f3',\n      range.fields.net, range.fields.netPct,\n      range.fields.super, range.fields.big, range.fields.medium, range.fields.small,\n    ];\n\n    const url = new URL('https://push2.eastmoney.com/api/qt/clist/get');\n    url.searchParams.set('pn', '1');\n    url.searchParams.set('pz', String(limit));\n    url.searchParams.set('po', po);\n    url.searchParams.set('np', '1');\n    url.searchParams.set('fltt', '2');\n    url.searchParams.set('invt', '2');\n    url.searchParams.set('fid', range.fid);\n    url.searchParams.set('fs', A_MARKET);\n    url.searchParams.set('fields', fieldList.join(','));\n    url.searchParams.set('ut', 'b2884a393a59ad64002292a3e90d46a5');\n\n    const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\n    if (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow failed: HTTP ${resp.status}`);\n    const data = await resp.json();\n    const diff = Array.isArray(data?.data?.diff) ? data.data.diff : [];\n    if (diff.length === 0) throw new CliError('NO_DATA', 'eastmoney returned no money-flow data');\n\n    return diff.slice(0, limit).map((it, i) => ({\n      rank: i + 1,\n      code: it.f12,\n      name: it.f14,\n      price: it.f2,\n      changePercent: it.f3,\n      mainNet: it[range.fields.net],\n      mainNetRatio: it[range.fields.netPct],\n      superNet: it[range.fields.super],\n      bigNet: it[range.fields.big],\n      mediumNet: it[range.fields.medium],\n      smallNet: it[range.fields.small],\n    }));\n  },","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/eastmoney/money-flow.js#L42-L78","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\nif (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow failed: HTTP ${resp.status}`);\n// after — honor Retry-After on 429, retry transient failures\nconst resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\nif (resp.status === 429) {\n  const wait = Number(resp.headers.get('retry-after')) || 5;\n  await new Promise((r) => setTimeout(r, wait * 1000));\n}\nif (!resp.ok) throw new CliError('HTTP_ERROR', `money-flow failed: HTTP ${resp.status}`);","handlingStrategy":"retry","validationCode":"// Reachability pre-check before hitting the data endpoint\nconst probe = await fetch('https://push2.eastmoney.com', { headers: { 'User-Agent': 'Mozilla/5.0' } });\nif (!probe.ok && (probe.status === 403 || probe.status === 429)) console.warn('eastmoney throttling detected; add delays before calling money-flow');","typeGuard":"function isCliError(e) { return e instanceof Error && 'code' in e; }\nfunction isHttpError(e) { return isCliError(e) && e.code === 'HTTP_ERROR'; }","tryCatchPattern":"async function fetchMoneyFlowWithRetry(args, attempts = 3) {\n  for (let i = 0; ; i++) {\n    try { return await runMoneyFlow(args); }\n    catch (err) {\n      const retryable = err instanceof CliError && err.code === 'HTTP_ERROR' && /HTTP (429|5\\d\\d)/.test(err.message);\n      if (!retryable || i >= attempts - 1) throw err;\n      await new Promise((r) => setTimeout(r, 2000 * 2 ** i)); // exponential backoff\n    }\n  }\n}","preventionTips":["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."],"tags":["http","network","api","eastmoney","rate-limit"],"backgroundTag":"http-non-2xx-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}