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
- Test the name against /^[a-z0-9]([_.-]?[a-z0-9]+)*$/ per segment and fix the offending characters.
- Remove doubled or leading/trailing separators: 'laravel--' -> 'laravel'.
- Verify the exact vendor/package on packagist.org and copy it verbatim.
- 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
- Copy exact package names from packagist.org rather than typing from memory.
- Validate against the SEGMENT regex in your own tooling before calling.
- Collapse doubled separators and strip spaces/uppercase punctuation from pasted names.
- Fall back to the search command when validation fails.
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
- packagist package "${value}" must be "<vendor>/<package>"
- packagist package name is required (e.g. "symfony/console",
- coingecko currency must look like a currency slug (got "${ar
- crates crate name "${value}" is not a valid crates.io name
- designer must be a Dribbble username or profile slug
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/46a78e5cdb13bca0.
Report an issue: GitHub.