jackwener/OpenCLI · error · CommandExecutionError

HN API HTTP ${res.status} for item ${id}

Error message

HN API HTTP ${res.status} for item ${id}

What it means

fetchItem calls the Hacker News Firebase API (hacker-news.firebaseio.com/v0/item/{id}.json) and throws CommandExecutionError with a hint when the response is not OK. It is used by story, fetched, and replies to load HN items by numeric id.

Source

Thrown at clis/hackernews/read.js:21

 *
 * Mirrors `reddit read` semantics — fetches a story plus a tree of top-level
 * comments and inline replies via the public Firebase API:
 *   https://hacker-news.firebaseio.com/v0/item/<id>.json
 *
 * Output rows:
 *   - first row is the story itself (`type=POST`)
 *   - each subsequent row is a comment, indented by depth (`L0`, `L1`, …)
 *   - `[+N more replies]` summary rows whenever depth/limit cuts in
 */
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';

const HN_ITEM_BASE = 'https://hacker-news.firebaseio.com/v0/item';

async function fetchItem(id) {
    const res = await fetch(`${HN_ITEM_BASE}/${id}.json`);
    if (!res.ok) {
        throw new CommandExecutionError(`HN API HTTP ${res.status} for item ${id}`, 'Check the item ID');
    }
    return res.json();
}

function requirePositiveInt(value, label) {
    if (!Number.isInteger(value) || value <= 0) {
        throw new ArgumentError(`${label} must be a positive integer`);
    }
    return value;
}

function requireMinInt(value, min, label) {
    if (!Number.isInteger(value) || value < min) {
        throw new ArgumentError(`${label} must be an integer >= ${min}`);
    }
    return value;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the item id exists: open https://news.ycombinator.com/item?id=<id> in a browser
  2. Check HN API status (https://hn.algolia.com/api or Firebase health) and retry later
  3. Only pass positive integers — validate with requirePositiveInt before fetching
  4. Add retry with exponential backoff for 429/5xx responses

Example fix

// before
await fetchItem('abc');
// HN API HTTP 400 for item abc

// after
const id = requirePositiveInt(Number(rawId), 'item id');
const item = await fetchItem(id);
Defensive patterns

Strategy: try-catch

Validate before calling

function isValidHnId(v){ return Number.isInteger(v) && v > 0; }
if (!isValidHnId(id)) throw new Error('HN item id must be a positive integer');

Type guard

const isHnHttpError = (e) => e instanceof CommandExecutionError && /HN API HTTP \d+/.test(e.message);

Try / catch

try {
  const item = await fetchItem(id);
} catch (e) {
  if (isHnHttpError(e) && /HTTP (429|5\d\d)/.test(e.message)) {
    return retryWithBackoff(() => fetchItem(id), 3);
  }
  throw e;
}

Prevention

When it happens

Trigger: fetchItem(id) receiving a non-2xx response: malformed/nonexistent numeric id (400/404), HN API outage or rate-limit (403/429/5xx), or Firebase downtime.

Common situations: Typing a wrong or too-large story id; HN/Firebase API returning 5xx during incidents; aggressive polling hitting Firebase limits; the v0 endpoint being temporarily unavailable.

Related errors


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