jackwener/OpenCLI · warning · EmptyResultError
hackernews/${id}
Error message
hackernews/${id} What it means
`EmptyResultError` is thrown when the fetched HN item does not exist or has been removed: the Firebase API returns `null` for an unknown id, or the item carries `deleted: true` / `dead: true`. The error's resource is `hackernews/<id>` with hint 'Story not found, deleted, or dead'. This is an expected outcome for removed content, not a network failure.
Source
Thrown at clis/hackernews/read.js:100
{ name: 'limit', type: 'int', default: 25, help: 'Max top-level comments' },
{ name: 'depth', type: 'int', default: 2, help: 'Max reply depth (1=no replies, 2=one level of replies, etc.)' },
{ name: 'replies', type: 'int', default: 5, help: 'Max replies shown per comment at each level' },
{ name: 'max-length', type: 'int', default: 2000, help: 'Max characters per comment body (min 100)' },
],
columns: ['type', 'author', 'score', 'text'],
func: async (args) => {
const id = String(args.id || '').trim();
if (!/^\d+$/.test(id)) {
throw new ArgumentError(`Invalid HN item id: ${args.id}`, 'Pass a numeric id like 39847301');
}
const limit = requirePositiveInt(args.limit ?? 25, 'hackernews read --limit');
const maxDepth = requirePositiveInt(args.depth ?? 2, 'hackernews read --depth');
const maxReplies = requirePositiveInt(args.replies ?? 5, 'hackernews read --replies');
const maxLength = requireMinInt(args['max-length'] ?? 2000, 100, 'hackernews read --max-length');
const story = await fetchItem(id);
if (!story || story.deleted || story.dead) {
throw new EmptyResultError(`hackernews/${id}`, 'Story not found, deleted, or dead');
}
const results = [];
// Story header row. text combines title + selftext (Ask/Show HN body) + external URL.
const storyBodyRaw = htmlToText(story.text || '');
const storyBody = storyBodyRaw.length > maxLength
? storyBodyRaw.slice(0, maxLength) + '\n... [truncated]'
: storyBodyRaw;
const storyParts = [story.title || ''];
if (storyBody) storyParts.push('\n' + storyBody);
if (story.url) storyParts.push('\n' + story.url);
results.push({
type: 'POST',
author: story.by || '[deleted]',
score: story.score ?? 0,
text: storyParts.join('').trim(),
});View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the id on huggingface — open https://news.ycombinator.com/item?id=<id> in a browser to confirm it exists
- Double-check digits of the id (off-by-one typos look valid numerically)
- If the story was deleted/dead, find an alternative source (e.g. a mirror or the Wayback Machine) — the CLI cannot return removed content
Example fix
// before opencli hackernews read 398473011 // null item -> EmptyResultError // after opencli hackernews read 39847301 // live, valid story id
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check via the public Firebase API before invoking the CLI
const res = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
const item = await res.json();
if (!item || item.deleted || item.dead) {
console.warn(`HN item ${id} is missing/deleted/dead; skipping`);
} Type guard
function isLiveStory(item) {
return item != null && item.deleted !== true && item.dead !== true;
} Try / catch
try {
await run(['opencli', 'hackernews', 'read', id]);
} catch (e) {
if (e.name === 'EmptyResultError' || String(e.message).includes('hackernews/')) {
console.warn(`Story ${id} not found, deleted, or dead; skipping`);
} else throw e;
} Prevention
- Treat HN ids as ephemeral — deleted/dead items are common and unrecoverable via the API
- Pre-check items with the Firebase endpoint when batch-processing old id lists
- Verify ids against news.ycombinator.com/item?id=<id> before scripting around them
When it happens
Trigger: Calling `hackernews read` with a numeric but nonexistent id (HN returns null); reading a story/comment that moderators killed or the author deleted; ids of items that were never stories (e.g. poll items are handled but some item types may be absent).
Common situations: Re-running scripts on ids saved weeks/months earlier whose stories were since deleted; typos in an otherwise valid numeric id (e.g. 398473011 vs 39847301); scraping archived lists containing dead HN posts.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- bilibili creator-stats ${bvid}
- Chess.com returned 404 for ${url}
- crates crate
- crates.io returned 404 for ${url}.
- Photo ID ${requestedPhotoId} was not found under subject ${s
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c242af7d958a9acf.
Report an issue: GitHub.