jackwener/OpenCLI · warning · CliError
NO_DATA
NO_DATA
Error message
`No longhu data since ${sinceDate}` What it means
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.
Source
Thrown at clis/eastmoney/longhu.js:50
const limit = Math.max(1, Math.min(Number(args.limit) || 20, 100));
const url = new URL('https://datacenter-web.eastmoney.com/api/data/v1/get');
url.searchParams.set('sortColumns', 'TRADE_DATE,SECURITY_CODE');
url.searchParams.set('sortTypes', '-1,1');
url.searchParams.set('pageSize', String(limit));
url.searchParams.set('pageNumber', '1');
url.searchParams.set('reportName', 'RPT_DAILYBILLBOARD_DETAILS');
url.searchParams.set('columns', 'ALL');
url.searchParams.set('source', 'WEB');
url.searchParams.set('client', 'WEB');
url.searchParams.set('filter', `(TRADE_DATE>='${sinceDate}')`);
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
if (!resp.ok) throw new CliError('HTTP_ERROR', `longhu failed: HTTP ${resp.status}`);
const data = await resp.json();
/** @type {any[]} */
const rows = Array.isArray(data?.result?.data) ? data.result.data : [];
if (rows.length === 0) throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);
return rows.slice(0, limit).map((it) => ({
tradeDate: String(it.TRADE_DATE || '').slice(0, 10),
code: it.SECURITY_CODE,
name: it.SECURITY_NAME_ABBR,
closePrice: it.CLOSE_PRICE,
changeRate: it.CHANGE_RATE,
boardAmt: it.BILLBOARD_DEAL_AMT,
buyAmt: it.BILLBOARD_BUY_AMT,
sellAmt: it.BILLBOARD_SELL_AMT,
netAmt: it.BILLBOARD_NET_AMT,
turnover: it.ACCUM_AMOUNT,
dealRatio: it.DEAL_AMOUNT_RATIO,
market: it.TRADE_MARKET,
reason: it.EXPLANATION,
}));
},
});View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before
const rows = Array.isArray(data?.result?.data) ? data.result.data : [];
if (rows.length === 0) throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);
// after — widen the window before giving up
const rows = Array.isArray(data?.result?.data) ? data.result.data : [];
if (rows.length === 0) {
const wider = new Date(sinceDate);
wider.setDate(wider.getDate() - 7);
console.warn(`No longhu data since ${sinceDate}; try --since ${wider.toISOString().slice(0, 10)} or check it is a trading day`);
throw new CliError('NO_DATA', `No longhu data since ${sinceDate}`);
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check: is the requested date a likely trading day (skip weekends)?
function isLikelyTradingDay(d) { const day = new Date(d + 'T00:00:00Z').getUTCDay(); return day !== 0 && day !== 6; }
if (!isLikelyTradingDay(sinceDate)) console.warn(`${sinceDate} may be a non-trading day; NO_DATA is expected`); Type guard
function hasRows(data) { return Array.isArray(data?.result?.data) && data.result.data.length > 0; } Try / catch
try {
const rows = await getLonghu({ since: sinceDate });
} catch (err) {
if (err instanceof CliError && err.code === 'NO_DATA') {
const prev = shiftDays(sinceDate, -7); // fall back to a wider window
return getLonghu({ since: prev });
}
throw err;
} Prevention
- 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).
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8f5b350874df4859.
Report an issue: GitHub.