{"record":{"id":"9520cfd8b9aced7a","repo":"jackwener/OpenCLI","slug":"http-error-9520cf","errorCode":"HTTP_ERROR","errorMessage":"`eastmoney rank failed: HTTP ${resp.status}`","messagePattern":"`eastmoney rank failed: HTTP (.+?)`","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/eastmoney/rank.js","lineNumber":74,"sourceCode":"    const sort = SORTS[sortKey];\n    if (!sort) {\n      throw new CliError('INVALID_ARGUMENT', `Unknown sort \"${sortKey}\". Valid: ${Object.keys(SORTS).join(', ')}`);\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', sort.order === 'desc' ? '1' : '0');\n    url.searchParams.set('np', '1');\n    url.searchParams.set('fltt', '2');\n    url.searchParams.set('invt', '2');\n    url.searchParams.set('fid', sort.fid);\n    url.searchParams.set('fs', fs);\n    url.searchParams.set('fields', FIELDS);\n    url.searchParams.set('ut', 'bd1d9ddb04089700cf9c27f6f7426281');\n\n    const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0', Accept: 'application/json' } });\n    if (!resp.ok) throw new CliError('HTTP_ERROR', `eastmoney rank 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) {\n      throw new CliError('NO_DATA', 'eastmoney returned no rank data', `market=${market} sort=${sortKey}`);\n    }\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      change: it.f4,\n      turnover: it.f6,\n      volume: it.f5,\n      turnoverRate: it.f8,\n      peDynamic: it.f9,\n      marketCap: it.f20,","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/eastmoney/rank.js#L56-L92","documentation":"The eastmoney rank CLI fetches stock ranking data from the push2.eastmoney.com clist API. It throws this CliError with code HTTP_ERROR whenever the HTTP response status is not ok (e.g. 4xx/5xx), aborting before JSON parsing so the caller gets a clear upstream-failure message with the status code.","triggerScenarios":"Any non-2xx response from https://push2.eastmoney.com/api/qt/clist/get while running the rank command — e.g. the eastmoney API rate-limits, blocks the UA/IP, returns 403/429, or the endpoint is temporarily down.","commonSituations":"Running the CLI from an IP region blocked by eastmoney, hammering the endpoint in a loop and hitting rate limiting, eastmoney serving HTML error pages during outages, or a corporate proxy returning 4xx/5xx.","solutions":["Re-run the command after a short wait; the failure is usually transient","Check the HTTP status in the message: 403/429 means blocked or rate-limited — reduce request frequency or change network/IP (VPN/proxy)","Verify network access to push2.eastmoney.com (curl -I with a browser User-Agent)","Retry with a different market/sort parameter in case a specific query combination is rejected"],"exampleFix":"// before: raw fetch failure surfaces as generic fetch error\nconst resp = await fetch(url);\n// after (library already does this; caller should catch)\ntry { await rank({ market: 'hsa', sort: 'change' }); } catch (e) { if (e.code === 'HTTP_ERROR') console.error('eastmoney unavailable:', e.message); }","handlingStrategy":"try-catch","validationCode":"const url = new URL('https://push2.eastmoney.com/api/qt/clist/get');\n// preflight reachability\nconst ping = await fetch(url, { method: 'HEAD' }).catch(() => null);\nif (!ping || !ping.ok) console.warn('eastmoney endpoint not reachable, status', ping?.status);","typeGuard":"function isHttpCliError(e) { return e && typeof e === 'object' && e.code === 'HTTP_ERROR' && typeof e.message === 'string'; }","tryCatchPattern":"try {\n  const rows = await rank({ market: 'hsa', sort: 'change' });\n} catch (e) {\n  if (e.code === 'HTTP_ERROR') {\n    const status = /HTTP (\\d{3})/.exec(e.message)?.[1];\n    if (status === '429' || status?.startsWith('5')) await retryWithBackoff();\n    else console.error('eastmoney rejected request:', e.message);\n  } else throw e;\n}","preventionTips":["Add exponential backoff for 429/5xx responses","Reuse a realistic User-Agent and avoid aggressive polling intervals","Monitor eastmoney endpoint health before batch runs","Cache recent results so transient HTTP failures don't break workflows"],"tags":["http","network","api","eastmoney"],"backgroundTag":"upstream-http-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}