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
- Verify the item id exists: open https://news.ycombinator.com/item?id=<id> in a browser
- Check HN API status (https://hn.algolia.com/api or Firebase health) and retry later
- Only pass positive integers — validate with requirePositiveInt before fetching
- 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
- Validate ids with requirePositiveInt before calling fetchItem
- Cache fetched items to reduce API calls and rate-limit risk
- Retry only on 429/5xx; 404 means the id genuinely does not exist
- Check HN API status during outages before debugging your own code
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
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- HTTP ${result.httpStatus} from /api/organizations
- ${label} returned HTTP ${res.status}
- HTTP_ERROR
- HTTP_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9c56b21b03a679e4.
Report an issue: GitHub.