{"record":{"id":"636675c6f3971407","repo":"jackwener/OpenCLI","slug":"pypi-package-name-is-required-e-g-requests-p","errorCode":null,"errorMessage":"pypi package name is required (e.g. \"requests\", \"pandas\")","messagePattern":"pypi package name is required \\(e\\.g\\. \"requests\", \"pandas\"\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pypi/utils.js","lineNumber":14,"sourceCode":"// Shared helpers for the pypi adapters that hit the PyPI public JSON API\n// (pypi.org/pypi/<pkg>/json) and pypistats.org for download stats.\nimport { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const PYPI_BASE = 'https://pypi.org';\nexport const PYPISTATS_BASE = 'https://pypistats.org';\nconst UA = 'opencli-pypi-adapter (+https://github.com/jackwener/opencli)';\n\n// PEP 508 / PEP 426 normalized name: letters, digits, \"._-\", with leading-letter rule relaxed by PyPI.\nconst PKG_NAME = /^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$/;\n\nexport function requirePackageName(value) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError('pypi package name is required (e.g. \"requests\", \"pandas\")');\n    if (!PKG_NAME.test(s)) {\n        throw new ArgumentError(\n            `pypi package name \"${value}\" is not a valid distribution name`,\n            'PyPI accepts ASCII letters / digits / \"._-\" with no leading or trailing separator.',\n        );\n    }\n    return s;\n}\n\nexport async function pypiFetch(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 pypi.org / pypistats.org are reachable from this network.',","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pypi/utils.js#L1-L32","documentation":"ArgumentError thrown by requirePackageName when the package name argument is empty or missing. The helper trims the input and rejects blank strings before any network request is made. It fails fast with an example-bearing message so users know the expected input format.","triggerScenarios":"Calling a pypi CLI subcommand (e.g. `pypi package`, which calls requirePackageName via the `name` arg) with an empty string, whitespace-only string, null, or undefined name.","commonSituations":"Forgetting the positional argument in a script; a shell variable that resolves to empty (`pypi package \"$PKG\"` with unset PKG); piping config with a missing name field.","solutions":["Pass a package name explicitly, e.g. `pypi package requests`","Check the variable holding the name is set and non-empty","Validate required inputs in the calling script before invoking the CLI"],"exampleFix":"// before\nconst name = process.env.PKG; // may be undefined\nawait pypiPackage(name);\n// after\nif (!process.env.PKG) throw new Error('PKG env var required');\nawait pypiPackage(process.env.PKG);","handlingStrategy":"validation","validationCode":"const name = (process.argv[2] ?? '').trim();\nif (!name) {\n  console.error('Usage: pypi package <name>');\n  process.exit(2);\n}","typeGuard":"function isNonEmptyString(v) { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":"try {\n  await pypiPackage(name);\n} catch (e) {\n  if (/name is required/i.test(e.message)) {\n    console.error('Provide a package name, e.g. pypi package requests');\n  } else throw e;\n}","preventionTips":["Always validate CLI args before invoking the API","Check env/script variables for emptiness with ${VAR:?} guards in bash","Require explicit names in automation rather than relying on defaults"],"tags":["pypi","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}