jackwener/OpenCLI · error · ArgumentError

packagist package "${value}" is not a valid Composer name

Error message

packagist package "${value}" is not a valid Composer name

What it means

requirePackageName throws this ArgumentError when both segments exist and are within 100 chars, but at least one segment fails the Composer SEGMENT regex: ^[a-z0-9]([_.-]?[a-z0-9]+)*$. That regex requires lowercase letters/digits, allows single separators (_ . -) between runs, and disallows leading/trailing/doubled separators. Input is lowercased first, so uppercase letters alone are not the cause.

Source

Thrown at clis/packagist/utils.js:47

    return n;
}

export function requirePackageName(value) {
    const raw = String(value ?? '').trim().toLowerCase();
    if (!raw) {
        throw new ArgumentError('packagist package name is required (e.g. "symfony/console", "monolog/monolog")');
    }
    const slash = raw.indexOf('/');
    if (slash <= 0 || slash === raw.length - 1) {
        throw new ArgumentError(
            `packagist package "${value}" must be "<vendor>/<package>"`,
            'Both segments are required (Composer convention).',
        );
    }
    const vendor = raw.slice(0, slash);
    const pkg = raw.slice(slash + 1);
    if (vendor.length > 100 || pkg.length > 100 || !SEGMENT.test(vendor) || !SEGMENT.test(pkg)) {
        throw new ArgumentError(
            `packagist package "${value}" is not a valid Composer name`,
            'Use lowercase letters / digits / "_-.", segments separated by single "_-." chars (max 100 chars each).',
        );
    }
    return { vendor, package: pkg, full: `${vendor}/${pkg}` };
}

export async function packagistFetch(url, label) {
    let resp;
    try {
        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
    }
    catch (err) {
        throw new CommandExecutionError(
            `${label} request failed: ${err?.message ?? err}`,
            'Check that packagist.org is reachable from this network.',
        );
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Test the name against /^[a-z0-9]([_.-]?[a-z0-9]+)*$/ per segment and fix the offending characters.
  2. Remove doubled or leading/trailing separators: 'laravel--' -> 'laravel'.
  3. Verify the exact vendor/package on packagist.org and copy it verbatim.
  4. Catch ArgumentError and fall back to the search command to find the correct name.

Example fix

// before
await full('laravel--/framework'); // invalid segment separators

// after
await full('laravel/framework');
Defensive patterns

Strategy: validation

Validate before calling

const SEGMENT = /^[a-z0-9]([_.-]?[a-z0-9]+)*$/;
function isValidComposerName(v) {
  const s = String(v ?? '').trim().toLowerCase();
  const i = s.indexOf('/');
  if (i <= 0 || i === s.length - 1) return false;
  const [vendor, pkg] = [s.slice(0, i), s.slice(i + 1)];
  return vendor.length <= 100 && pkg.length <= 100 &&
    SEGMENT.test(vendor) && SEGMENT.test(pkg);
}
if (!isValidComposerName(name)) throw new Error(`invalid Composer name: ${name}`);

Type guard

const passesSegmentRegex = (seg) => /^[a-z0-9]([_.-]?[a-z0-9]+)*$/.test(seg);

Try / catch

try {
  await full(name);
} catch (e) {
  if (e instanceof ArgumentError && /not a valid Composer name/.test(e.message)) {
    const cleaned = name.toLowerCase().replace(/[^a-z0-9/.\-]+/g, '').replace(/([.\-])\1+/g, '$1');
    if (isValidComposerName(cleaned)) return full(cleaned);
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling full with names like 'symfony//console' (empty segment after first slash is caught earlier; but 'foo..bar/baz' with '..' inside a segment), '_foo/bar' (leading underscore), 'foo-/bar' (trailing separator), or a segment over 100 chars.

Common situations: Typos with doubled dashes/dots ('laravel--/framework'); names copied from non-Composer ecosystems containing spaces or uppercase-derived punctuation; truncation creating a trailing separator; guessing a vendor name that contains invalid characters.

Related errors


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