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

  1. Check whether the since date falls on a Chinese trading day — no longhu list is published on weekends/holidays; pick a recent trading day.
  2. Verify the sinceDate format matches 'YYYY-MM-DD' exactly as used in the TRADE_DATE filter string.
  3. Use a wider date window (an earlier since) to confirm data exists at all for the endpoint.
  4. 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.
  5. 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

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.