jackwener/OpenCLI · error · CliError

HTTP_ERROR

HTTP_ERROR

Error message

ths hot-rank failed: HTTP ${resp.status}

What it means

The ths hot-rank command fetches the 10jqka (同花顺) hot-stock ranking JSON endpoint and checks resp.ok. Any non-2xx HTTP status (403 anti-bot, 404, 5xx) throws CliError HTTP_ERROR with the status embedded in the message.

Source

Thrown at clis/ths/hot-rank.js:43

    access: 'read',
  description: '同花顺热股榜',
  domain: 'dq.10jqka.com.cn',
  strategy: Strategy.PUBLIC,
  browser: false,
  args: [
    { name: 'limit', type: 'int', default: 20, help: '返回数量' },
  ],
  columns: ['rank', 'name', 'changePercent', 'heat', 'tags'],
  func: async (args) => {
    const limit = parseLimit(args.limit);
    const resp = await fetch(THS_HOT_API_URL, {
      headers: {
        'Accept': 'application/json,text/plain,*/*',
        'User-Agent': 'Mozilla/5.0',
        'Referer': 'https://eq.10jqka.com.cn/',
      },
    });
    if (!resp.ok) throw new CliError('HTTP_ERROR', `ths hot-rank failed: HTTP ${resp.status}`);
    const payload = await resp.json();
    const stocks = Array.isArray(payload?.data?.stock_list) ? payload.data.stock_list : [];
    if (stocks.length === 0) throw new CliError('NO_DATA', 'ths hot-rank API returned no stock data');

    return stocks.slice(0, limit).map((stock, index) => ({
      rank: stock.order ?? index + 1,
      name: stock.name ?? '',
      changePercent: stock.rise_and_fall ?? '',
      heat: stock.rate ?? '',
      tags: tagsFromStock(stock),
    }));
  },
});

export const __test__ = {
  THS_HOT_API_URL,
  parseLimit,
  tagsFromStock,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry after a short backoff (transient 5xx/rate limit)
  2. Send browser-like headers including a real User-Agent and any required 10jqka cookies
  3. Check the endpoint URL is still valid in a browser and update clis/ths/hot-rank.js if the API moved
  4. Route through a proxy/egress IP not blocked by 10jqka if 403 persists

Example fix

// before
const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
// after
const resp = await fetch(url, { headers: browserHeaders });
if (!resp.ok) throw new CliError('HTTP_ERROR', `ths hot-rank failed: HTTP ${resp.status}`);
// add retry with backoff on 429/5xx before giving up
Defensive patterns

Strategy: retry

Validate before calling

// preflight: endpoint reachability
const head = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json' } });
if (!head.ok) console.warn(`ths endpoint unhealthy: HTTP ${head.status}`);

Try / catch

try {
  const stocks = await thsHotRank({ limit });
} catch (e) {
  if (e?.code === 'HTTP_ERROR') {
    await sleep(2000);
    return thsHotRank({ limit }); // retry once with backoff
  }
  throw e;
}

Prevention

When it happens

Trigger: HTTP fetch to the eq.10jqka.com.cn hot-rank API returning non-ok status: server error, rate-limit/WAF 403 due to missing cookies or blocked UA, or endpoint path change.

Common situations: 10jqka WAF blocking requests without browser cookies; temporary 5xx outage; ISP/region blocks; API endpoint renamed after site redesign.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f55faf4abdba388e. Report an issue: GitHub.