{"record":{"id":"8f5b350874df4859","repo":"jackwener/OpenCLI","slug":"no-data-8f5b35","errorCode":"NO_DATA","errorMessage":"`No longhu data since ${sinceDate}`","messagePattern":"`No longhu data since (.+?)`","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"warning","filePath":"clis/eastmoney/longhu.js","lineNumber":50,"sourceCode":"    const limit = Math.max(1, Math.min(Number(args.limit) || 20, 100));\n\n    const url = new URL('https://datacenter-web.eastmoney.com/api/data/v1/get');\n    url.searchParams.set('sortColumns', 'TRADE_DATE,SECURITY_CODE');\n    url.searchParams.set('sortTypes', '-1,1');\n    url.searchParams.set('pageSize', String(limit));\n    url.searchParams.set('pageNumber', '1');\n    url.searchParams.set('reportName', 'RPT_DAILYBILLBOARD_DETAILS');\n    url.searchParams.set('columns', 'ALL');\n    url.searchParams.set('source', 'WEB');\n    url.searchParams.set('client', 'WEB');\n    url.searchParams.set('filter', `(TRADE_DATE>='${sinceDate}')`);\n\n    const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\n    if (!resp.ok) throw new CliError('HTTP_ERROR', `longhu failed: HTTP ${resp.status}`);\n    const data = await resp.json();\n    /** @type {any[]} */\n    const rows = Array.isArray(data?.result?.data) ? data.result.data : [];\n    if (rows.length === 0) throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);\n\n    return rows.slice(0, limit).map((it) => ({\n      tradeDate: String(it.TRADE_DATE || '').slice(0, 10),\n      code: it.SECURITY_CODE,\n      name: it.SECURITY_NAME_ABBR,\n      closePrice: it.CLOSE_PRICE,\n      changeRate: it.CHANGE_RATE,\n      boardAmt: it.BILLBOARD_DEAL_AMT,\n      buyAmt: it.BILLBOARD_BUY_AMT,\n      sellAmt: it.BILLBOARD_SELL_AMT,\n      netAmt: it.BILLBOARD_NET_AMT,\n      turnover: it.ACCUM_AMOUNT,\n      dealRatio: it.DEAL_AMOUNT_RATIO,\n      market: it.TRADE_MARKET,\n      reason: it.EXPLANATION,\n    }));\n  },\n});","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/eastmoney/longhu.js#L32-L68","documentation":"The eastmoney longhu CLI throws CliError('NO_DATA') when the API responds successfully but `data.result.data` is missing or not an array, i.e. zero Dragon-Tiger list rows match the requested date range. This distinguishes an empty-but-healthy upstream response from a transport failure (HTTP_ERROR). The message includes the sinceDate so the caller knows which window returned nothing.","triggerScenarios":"Calling the longhu command with a `since` date range that contains no published Dragon-Tiger data — e.g. a future date, a weekend/holiday window, a date before records exist, or when the sinceDate string format doesn't match TRADE_DATE so the server-side filter matches nothing. Also fires if eastmoney changes its JSON envelope shape (result.data renamed/moved).","commonSituations":"Querying on a non-trading day (weekends, Chinese public holidays) when no longhu list is published; using the wrong date format for the filter; running soon after midnight before the exchange publishes the list; a silent eastmoney API schema change breaking the result.data path.","solutions":["Check whether the since date falls on a Chinese trading day — no longhu list is published on weekends/holidays; pick a recent trading day.","Verify the sinceDate format matches 'YYYY-MM-DD' exactly as used in the TRADE_DATE filter string.","Use a wider date window (an earlier since) to confirm data exists at all for the endpoint.","If data exists on the website but not via the CLI, inspect the raw JSON (data.result) for an eastmoney envelope/schema change and update the row-extraction path.","Delay runs until after the daily publication time of the Dragon-Tiger list rather than running immediately at market close."],"exampleFix":"// before\nconst rows = Array.isArray(data?.result?.data) ? data.result.data : [];\nif (rows.length === 0) throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);\n// after — widen the window before giving up\nconst rows = Array.isArray(data?.result?.data) ? data.result.data : [];\nif (rows.length === 0) {\n  const wider = new Date(sinceDate);\n  wider.setDate(wider.getDate() - 7);\n  console.warn(`No longhu data since ${sinceDate}; try --since ${wider.toISOString().slice(0, 10)} or check it is a trading day`);\n  throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);\n}","handlingStrategy":"fallback","validationCode":"// Pre-check: is the requested date a likely trading day (skip weekends)?\nfunction isLikelyTradingDay(d) { const day = new Date(d + 'T00:00:00Z').getUTCDay(); return day !== 0 && day !== 6; }\nif (!isLikelyTradingDay(sinceDate)) console.warn(`${sinceDate} may be a non-trading day; NO_DATA is expected`);","typeGuard":"function hasRows(data) { return Array.isArray(data?.result?.data) && data.result.data.length > 0; }","tryCatchPattern":"try {\n  const rows = await getLonghu({ since: sinceDate });\n} catch (err) {\n  if (err instanceof CliError && err.code === 'NO_DATA') {\n    const prev = shiftDays(sinceDate, -7); // fall back to a wider window\n    return getLonghu({ since: prev });\n  }\n  throw err;\n}","preventionTips":["Schedule longhu queries after the daily list publication time and only on trading days.","Default the since window to several days back instead of a single day.","Validate the date format is exactly YYYY-MM-DD before calling.","Check eastmoney's website for data availability before scripting the same window.","Handle NO_DATA as a normal, non-fatal outcome in scheduled jobs (exit 66-style semantics)."],"tags":["empty-result","api","eastmoney","date-range"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}