{"record":{"id":"ef4e320808824d9a","repo":"jackwener/OpenCLI","slug":"osv-ecosystem-value-is-not-a-recognised-osv","errorCode":null,"errorMessage":"osv --ecosystem \"${value}\" is not a recognised OSV ecosystem","messagePattern":"osv --ecosystem \"(.+?)\" is not a recognised OSV ecosystem","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/osv/utils.js","lineNumber":66,"sourceCode":"    if (!VULN_ID.test(s)) {\n        throw new ArgumentError(\n            `osv vulnerability id \"${value}\" is not a valid OSV id`,\n            'IDs are short ASCII tokens like \"GHSA-...\", \"CVE-...\", \"PYSEC-...\".',\n        );\n    }\n    return s;\n}\n\nexport function requireEcosystem(value) {\n    const s = String(value ?? '').trim();\n    if (!s) {\n        throw new ArgumentError(\n            'osv --ecosystem is required when querying by package',\n            `Pick one of: ${[...OSV_ECOSYSTEMS].join(', ')}.`,\n        );\n    }\n    if (!OSV_ECOSYSTEMS.has(s)) {\n        throw new ArgumentError(\n            `osv --ecosystem \"${value}\" is not a recognised OSV ecosystem`,\n            `Pick one of: ${[...OSV_ECOSYSTEMS].join(', ')}.`,\n        );\n    }\n    return s;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`osv ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`osv ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/osv/utils.js#L48-L84","documentation":"requireEcosystem validates the value against the OSV_ECOSYSTEMS allowlist; unknown strings are rejected. OSV ecosystems are case-sensitive registry names (e.g. 'PyPI', not 'pypi'; 'crates.io', not 'cargo').","triggerScenarios":"Passing an unsupported or misspelled ecosystem: 'node', 'javascript', 'pypi', 'cargo', 'ruby', 'CRATES.IO', etc.","commonSituations":"Guessing ecosystem names instead of using registry names; lowercase normalization from config files; mapping language names rather than package-manager names.","solutions":["Use an exact value from the allowlist: npm, PyPI, Go, Maven, NuGet, RubyGems, crates.io, Packagist, Pub, Hex, Hackage, CRAN, Bitnami, GitHub Actions, SwiftURL.","Fix casing to match the canonical OSV name (PyPI, RubyGems, crates.io).","Map common aliases in your wrapper (node→npm, cargo→crates.io, pip→PyPI).","Consult https://ossf.github.io/osv-schema/#defined-ecosystems for canonical names."],"exampleFix":"// before\nrequireEcosystem('pypi');\n// after\nrequireEcosystem('PyPI');","handlingStrategy":"validation","validationCode":"const OSV_ECOSYSTEMS = new Set(['npm','PyPI','Go','Maven','NuGet','RubyGems','crates.io','Packagist','Pub','Hex','Hackage','CRAN','Bitnami','GitHub Actions','SwiftURL']);\nif (!OSV_ECOSYSTEMS.has(ecosystem)) {\n  throw new Error(`Unknown ecosystem \"${ecosystem}\" — use one of: ${[...OSV_ECOSYSTEMS].join(', ')}`);\n}","typeGuard":"const isKnownEcosystem = (v) =>\n  typeof v === 'string' && OSV_ECOSYSTEMS.has(v.trim());","tryCatchPattern":"try {\n  const result = await osvQuery({ ecosystem, name });\n} catch (e) {\n  if (e instanceof ArgumentError && /not a recognised OSV ecosystem/.test(e.message)) {\n    console.error('Fix the ecosystem name/case, e.g. pypi→PyPI, cargo→crates.io');\n    return;\n  }\n  throw e;\n}","preventionTips":["Normalize aliases (node→npm, cargo→crates.io, pip→PyPI, ruby→RubyGems) in wrappers.","Preserve exact casing from the canonical list; never lowercase ecosystem names.","Copy ecosystem values from the official OSV schema list.","Validate ecosystem values at config-load time, not at query time."],"tags":["enum-validation","input-validation","osv"],"backgroundTag":"invalid-enum-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}