{"record":{"id":"2f994b663b92afee","repo":"jackwener/OpenCLI","slug":"story-not-found","errorCode":null,"errorMessage":"Story not found","messagePattern":"Story not found","errorType":"exception","errorClass":"EmptyResultError","httpStatus":404,"severity":"error","filePath":"clis/lobsters/read.js","lineNumber":23,"sourceCode":" *   https://lobste.rs/s/<short_id>.json\n * already returns the story plus a flat `comments[]` array where each entry\n * carries `parent_comment` (short_id of parent or null) and `depth` — so we\n * just need one HTTP call, then build a children map and DFS.\n *\n * Output rows:\n *   - first row is the story itself (`type=POST`)\n *   - each subsequent row is a comment, indented by depth (`L0`, `L1`, …)\n *   - `[+N more replies]` summary rows whenever depth/limit cuts in\n */\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nconst LOBSTERS_STORY_BASE = 'https://lobste.rs/s';\n\nasync function fetchStory(shortId) {\n    const res = await fetch(`${LOBSTERS_STORY_BASE}/${shortId}.json`);\n    if (res.status === 404) {\n        throw new EmptyResultError(`lobsters/${shortId}`, 'Story not found');\n    }\n    if (!res.ok) {\n        throw new CommandExecutionError(`Lobsters API HTTP ${res.status} for story ${shortId}`, 'Check the short id');\n    }\n    return res.json();\n}\n\nfunction requirePositiveInt(value, label) {\n    if (!Number.isInteger(value) || value <= 0) {\n        throw new ArgumentError(`${label} must be a positive integer`);\n    }\n    return value;\n}\n\nfunction requireMinInt(value, min, label) {\n    if (!Number.isInteger(value) || value < min) {\n        throw new ArgumentError(`${label} must be an integer >= ${min}`);\n    }","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/lobsters/read.js#L5-L41","documentation":"This EmptyResultError is thrown by fetchStory (invoked by the `lobsters read` command) when GET https://lobste.rs/s/<shortId>.json returns HTTP 404, meaning no story exists with that short id on Lobste.rs. It distinguishes 'unknown/deleted story id' from transport failures, which raise CommandExecutionError instead.","triggerScenarios":"Running `lobsters read <shortId>` where the id does not match any story: a typo in the short id, a story deleted or removed by moderators, an id copied from another site (Hacker News ids are numeric and will 404), or a truncated id.","commonSituations":"Hand-typing a short id from memory, using a HN numeric id like '12345678', referencing a story that was since deleted on lobste.rs, or off-by-one copy/paste of the id from a URL (extra characters or missing tail).","solutions":["Re-copy the short id from the story URL https://lobste.rs/s/<shortId> and verify it opens in a browser.","Confirm the id comes from Lobste.rs, not another aggregator (HN/Reddit ids will not resolve).","List stories again via `lobsters` front-page/domain commands to get a currently valid short id.","In scripts, catch EmptyResultError and prompt the user to re-enter the id instead of crashing."],"exampleFix":"// before\nawait cli.lobsters.read('12345678'); // HN-style numeric id -> Story not found\n\n// after\nconst id = 'abcdefgh'; // copy from the lobste.rs story URL /s/<id>\nawait cli.lobsters.read(id);","handlingStrategy":"validation","validationCode":"function isValidLobstersShortId(id) {\n  return typeof id === 'string' && /^[a-z0-9]{5,10}$/i.test(id);\n}\nif (!isValidLobstersShortId(shortId)) {\n  console.error(`\"${shortId}\" does not look like a Lobste.rs short id (copy it from https://lobste.rs/s/<id>).`);\n  process.exit(1);\n}","typeGuard":"null","tryCatchPattern":"try {\n  const story = await cli.lobsters.read(shortId);\n} catch (err) {\n  if (err.name === 'EmptyResultError') {\n    console.error(`No story with id \"${shortId}\" on Lobste.rs — check the id or the story may have been removed.`);\n    return;\n  }\n  throw err;\n}","preventionTips":["Always copy short ids directly from lobste.rs story URLs (/s/<id>), never type them from memory.","Do not use ids from other aggregators — Hacker News numeric ids will always 404 here.","Re-fetch a fresh id list via front-page/domain commands if a previously valid id starts failing (story may have been deleted).","Validate id shape (short alphanumeric string) before calling the read command in scripts."],"tags":["not-found","http-404","cli","user-input"],"backgroundTag":"resource-not-found-404","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}