jackwener/OpenCLI · error · ArgumentError

Invalid HN item id: ${args.id}

Error message

Invalid HN item id: ${args.id}

What it means

The `hackernews read` command requires its positional `id` argument to be a purely numeric HN item id (`/^\d+$/`). If the id is missing, empty, or contains any non-digit character, it throws `ArgumentError` with the hint 'Pass a numeric id like 39847301'. This check runs before validation of other flags or any API call.

Source

Thrown at clis/hackernews/read.js:91

    site: 'hackernews',
    name: 'read',
    access: 'read',
    description: 'Read a Hacker News story and its comment tree',
    domain: 'news.ycombinator.com',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'id', required: true, positional: true, help: 'HN item ID (e.g. 39847301)' },
        { 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;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass only the numeric item id, e.g. `opencli hackernews read 39847301`
  2. If you have a full HN URL, extract the `id=` query parameter first (e.g. `${url##*id=}` in bash)
  3. Quote shell variables (`"$id"`) and verify they are non-empty and all digits before invoking

Example fix

// before
opencli hackernews read "https://news.ycombinator.com/item?id=39847301"
// after
opencli hackernews read 39847301
Defensive patterns

Strategy: validation

Validate before calling

function extractHnId(input) {
  const m = String(input).match(/id=(\d+)/); // full HN URL form
  const id = m ? m[1] : String(input).trim();
  if (!/^\d+$/.test(id)) throw new Error(`Not a numeric HN item id: ${input}`);
  return id;
}
const id = extractHnId(rawInput);

Type guard

function isHnItemId(v) {
  return typeof v === 'string' && /^\d+$/.test(v.trim());
}

Try / catch

try {
  await run(['opencli', 'hackernews', 'read', id]);
} catch (e) {
  if (String(e.message).startsWith('Invalid HN item id')) {
    console.error(`Normalize input to bare digits; got: ${id}`);
  } else throw e;
}

Prevention

When it happens

Trigger: Running `hackernews read` with no id, with a story URL or slug instead of a numeric id (e.g. `https://news.ycombinator.com/item?id=...` pasted whole), an id containing whitespace/letters (e.g. `39847301a`), or shell variables that expand to empty.

Common situations: Pasting a full HN link instead of just the item number; automations extracting ids with regex that captured trailing punctuation or HTML entities; quoting bugs in shell scripts yielding empty strings.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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