jackwener/OpenCLI · error · ArgumentError

endoflife product is required (e.g. "nodejs", "python", "ubu

Error message

endoflife product is required (e.g. "nodejs", "python", "ubuntu")

What it means

requireProduct normalizes and validates the endoflife product slug. If the value is empty/missing after trimming and lowercasing, it throws an ArgumentError stating a product slug is required, with a hint pointing to https://endoflife.date/<product>. This prevents issuing requests for an empty resource path.

Source

Thrown at clis/endoflife/utils.js:16

// Shared helpers for the endoflife.date adapters.
//
// endoflife.date publishes a free, unauthenticated REST API with cycle / EOL /
// LTS data for hundreds of products. Docs: https://endoflife.date/docs/api/
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';

export const EOL_BASE = 'https://endoflife.date/api';
const UA = 'opencli-endoflife-adapter (+https://github.com/jackwener/opencli)';

// endoflife.date product slugs are lowercase ascii + digits + dashes / dots, up to 80 chars.
const PRODUCT = /^[a-z0-9][a-z0-9._-]{0,79}$/;

export function requireProduct(value) {
    const s = String(value ?? '').trim().toLowerCase();
    if (!s) {
        throw new ArgumentError(
            'endoflife product is required (e.g. "nodejs", "python", "ubuntu")',
            'Use the slug visible at https://endoflife.date/<product>.',
        );
    }
    if (!PRODUCT.test(s)) {
        throw new ArgumentError(
            `endoflife product "${value}" is not a valid endoflife.date slug`,
            'Slugs are lowercase ASCII letters/digits/"._-", e.g. "nodejs", "python", "ubuntu".',
        );
    }
    return s;
}

export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
    const raw = value ?? defaultValue;
    const n = typeof raw === 'number' ? raw : Number(raw);
    if (!Number.isInteger(n) || n <= 0) {
        throw new ArgumentError(`endoflife ${label} must be a positive integer`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a valid product slug, e.g. product 'nodejs' or --product python
  2. Look up the correct slug at https://endoflife.date/<product>
  3. Check the config/env source supplying the product name isn't empty
  4. Pre-validate the argument in your script before invoking the CLI

Example fix

// before
const name = process.env.PRODUCT; // undefined
await product(name);
// after
if (!process.env.PRODUCT) throw new Error('set PRODUCT');
await product(process.env.PRODUCT);
Defensive patterns

Strategy: validation

Validate before calling

function requireProductArg(v) {
  const s = String(v ?? '').trim().toLowerCase();
  if (!s) throw new Error('product slug required, e.g. nodejs, python, ubuntu');
  return s;
}

Type guard

function hasProduct(v) { return typeof v === 'string' && v.trim().length > 0; }

Try / catch

try {
  await eolProduct(args.product);
} catch (e) {
  if (e instanceof ArgumentError) { console.error('usage: product <slug>'); process.exitCode = 2; }
  else throw e;
}

Prevention

When it happens

Trigger: Calling the endoflife product CLI/command without --product, or with an empty string, whitespace-only value, null, or undefined.

Common situations: Forgot to pass the product argument in a script, an env variable or config key feeding the slug is unset, pipeline upstream emits an empty field.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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