{"record":{"id":"46a78e5cdb13bca0","repo":"jackwener/OpenCLI","slug":"packagist-package-value-is-not-a-valid-compos","errorCode":null,"errorMessage":"packagist package \"${value}\" is not a valid Composer name","messagePattern":"packagist package \"(.+?)\" is not a valid Composer name","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/packagist/utils.js","lineNumber":47,"sourceCode":"    return n;\n}\n\nexport function requirePackageName(value) {\n    const raw = String(value ?? '').trim().toLowerCase();\n    if (!raw) {\n        throw new ArgumentError('packagist package name is required (e.g. \"symfony/console\", \"monolog/monolog\")');\n    }\n    const slash = raw.indexOf('/');\n    if (slash <= 0 || slash === raw.length - 1) {\n        throw new ArgumentError(\n            `packagist package \"${value}\" must be \"<vendor>/<package>\"`,\n            'Both segments are required (Composer convention).',\n        );\n    }\n    const vendor = raw.slice(0, slash);\n    const pkg = raw.slice(slash + 1);\n    if (vendor.length > 100 || pkg.length > 100 || !SEGMENT.test(vendor) || !SEGMENT.test(pkg)) {\n        throw new ArgumentError(\n            `packagist package \"${value}\" is not a valid Composer name`,\n            'Use lowercase letters / digits / \"_-.\", segments separated by single \"_-.\" chars (max 100 chars each).',\n        );\n    }\n    return { vendor, package: pkg, full: `${vendor}/${pkg}` };\n}\n\nexport async function packagistFetch(url, label) {\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });\n    }\n    catch (err) {\n        throw new CommandExecutionError(\n            `${label} request failed: ${err?.message ?? err}`,\n            'Check that packagist.org is reachable from this network.',\n        );\n    }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/packagist/utils.js#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait full('laravel--/framework'); // invalid segment separators\n\n// after\nawait full('laravel/framework');","handlingStrategy":"validation","validationCode":"const SEGMENT = /^[a-z0-9]([_.-]?[a-z0-9]+)*$/;\nfunction isValidComposerName(v) {\n  const s = String(v ?? '').trim().toLowerCase();\n  const i = s.indexOf('/');\n  if (i <= 0 || i === s.length - 1) return false;\n  const [vendor, pkg] = [s.slice(0, i), s.slice(i + 1)];\n  return vendor.length <= 100 && pkg.length <= 100 &&\n    SEGMENT.test(vendor) && SEGMENT.test(pkg);\n}\nif (!isValidComposerName(name)) throw new Error(`invalid Composer name: ${name}`);","typeGuard":"const passesSegmentRegex = (seg) => /^[a-z0-9]([_.-]?[a-z0-9]+)*$/.test(seg);","tryCatchPattern":"try {\n  await full(name);\n} catch (e) {\n  if (e instanceof ArgumentError && /not a valid Composer name/.test(e.message)) {\n    const cleaned = name.toLowerCase().replace(/[^a-z0-9/.\\-]+/g, '').replace(/([.\\-])\\1+/g, '$1');\n    if (isValidComposerName(cleaned)) return full(cleaned);\n    throw e;\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["argument-validation","regex","composer","naming","packagist"],"backgroundTag":"invalid-package-name-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}