{"record":{"id":"802eecacbfc4c054","repo":"jackwener/OpenCLI","slug":"no-data-802eec","errorCode":"NO_DATA","errorMessage":"eastmoney returned no index data","messagePattern":"eastmoney returned no index data","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"warning","filePath":"clis/eastmoney/index-board.js","lineNumber":74,"sourceCode":"      entries = [...INDEX_GROUPS.main, ...INDEX_GROUPS.hk, ...INDEX_GROUPS.us];\n    } else if (INDEX_GROUPS[group]) {\n      entries = INDEX_GROUPS[group];\n    } else {\n      throw new CliError('INVALID_ARGUMENT', `Unknown group \"${group}\". Valid: main, hk, us, all`);\n    }\n\n    const secids = entries.map(([secid]) => secid).join(',');\n    const url = new URL('https://push2.eastmoney.com/api/qt/ulist.np/get');\n    url.searchParams.set('secids', secids);\n    url.searchParams.set('fltt', '2');\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 index-board 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 index data');\n\n    // Preserve the order defined in INDEX_GROUPS regardless of API ordering\n    const byCode = new Map(diff.map((it) => [String(it.f12), it]));\n    return entries\n      .map(([secid, fallbackName]) => {\n        const code = secid.split('.')[1];\n        const it = byCode.get(code);\n        if (!it) return null;\n        return {\n          code,\n          name: it.f14 || fallbackName,\n          price: it.f2,\n          changePercent: it.f3,\n          change: it.f4,\n          open: it.f17,\n          high: it.f15,\n          low: it.f16,\n          prevClose: it.f18,","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/eastmoney/index-board.js#L56-L92","documentation":"This CliError with code NO_DATA is thrown when the Eastmoney index API answers HTTP 200 but data.data.diff is missing, not an array, or empty. The library treats an empty diff array as 'no index data' rather than returning an empty board. It means the request succeeded but the payload contained no usable quotes.","triggerScenarios":"All requested secids are invalid/unknown to the ulist.np/get endpoint (Eastmoney often returns 200 with null data instead of an error); Eastmoney returning {data: null} during maintenance; an API contract change where quotes moved to a different field; passing a group whose secids are all mistyped.","commonSituations":"Constructing custom secid lists with wrong market prefixes (e.g. 0.000300 instead of 1.000300 for CSI indexes); Eastmoney field naming changes (f12 etc.) after an API update; transient backend hiccups returning empty payloads; querying outside market data availability windows in rare maintenance windows.","solutions":["Verify each secid uses the correct market prefix (Shanghai indexes like 1.000001/1.000300, Shenzhen 0.399001)","Check Eastmoney's web index board to confirm the API is currently returning data at all","Log/re-inspect the raw response body once to see if the schema changed (e.g. diff moved or renamed)","Treat NO_DATA as retryable with a short backoff if it happens sporadically; escalate if persistent","Update FIELDS/endpoint if Eastmoney changed the API contract"],"exampleFix":"// before\nconst diff = Array.isArray(data?.data?.diff) ? data.data.diff : [];\nif (diff.length === 0) throw new CliError('NO_DATA', 'eastmoney returned no index data');\n// after (caller side)\ntry {\n  const board = await getIndexBoard({ group: 'main' });\n} catch (e) {\n  if (e.code === 'NO_DATA') return []; // render empty board instead of crashing\n  throw e;\n}","handlingStrategy":"fallback","validationCode":"function validateSecidPrefixes(secids) {\n  // Shanghai indexes use prefix 1, Shenzhen use 0 — wrong prefixes yield empty diff with HTTP 200\n  return secids.every((s) => /^(1\\.0\\d{5}|0\\.3\\d{5})$/.test(s));\n}","typeGuard":"function hasIndexData(data) {\n  return Array.isArray(data?.data?.diff) && data.data.diff.length > 0;\n}","tryCatchPattern":"try {\n  return await getIndexBoard({ group });\n} catch (err) {\n  if (err.code === 'NO_DATA') {\n    return FALLBACK_BOARD; // cached/last-known-good board or empty array\n  }\n  throw err;\n}","preventionTips":["Double-check market prefixes on every secid (1. for SH, 0. for SZ indexes)","Cache the last successful board and serve it when the API returns empty","Retry briefly on NO_DATA — some empty payloads are transient","Keep an eye on Eastmoney API schema changes; log raw bodies when diff is empty"],"tags":["empty-result","api","no-data","eastmoney"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}