{"record":{"id":"c0e202b25a6b488a","repo":"jackwener/OpenCLI","slug":"pypi-package","errorCode":null,"errorMessage":"pypi package","messagePattern":"pypi package","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"error","filePath":"clis/pypi/package.js","lineNumber":48,"sourceCode":"    name: 'package',\n    access: 'read',\n    description: 'Single PyPI package metadata (latest version, license, homepage, classifiers)',\n    domain: 'pypi.org',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'name', positional: true, required: true, help: 'PyPI package name (e.g. \"requests\", \"pandas\")' },\n    ],\n    columns: [\n        'name', 'latestVersion', 'summary', 'author', 'license', 'homepage', 'repository',\n        'requiresPython', 'keywords', 'releases', 'firstReleased', 'lastReleased', 'url',\n    ],\n    func: async (args) => {\n        const name = requirePackageName(args.name);\n        const body = await pypiFetch(`${PYPI_BASE}/pypi/${encodeURIComponent(name)}/json`, `pypi package ${name}`);\n        const info = body?.info;\n        if (!info || !info.name) {\n            throw new EmptyResultError('pypi package', `PyPI returned no metadata for \"${name}\".`);\n        }\n        const releases = body?.releases ?? {};\n        const releaseVersions = Object.keys(releases).filter((v) => Array.isArray(releases[v]) && releases[v].length > 0);\n        // earliest / latest release timestamps from the upload_time fields\n        let firstReleased = '';\n        let lastReleased = '';\n        for (const v of releaseVersions) {\n            for (const file of releases[v]) {\n                const t = String(file?.upload_time ?? '').slice(0, 10);\n                if (!t) continue;\n                if (!firstReleased || t < firstReleased) firstReleased = t;\n                if (!lastReleased || t > lastReleased) lastReleased = t;\n            }\n        }\n        return [{\n            name: String(info.name),\n            latestVersion: String(info.version ?? ''),\n            summary: String(info.summary ?? ''),","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pypi/package.js#L30-L66","documentation":"EmptyResultError thrown in the `pypi package` command when the PyPI JSON API responds successfully but contains no `info` object or no `info.name`. The CLI treats a metadata-less response as 'package produced no data' rather than silently returning an empty result. This guards against rendering broken output from an unexpected API payload.","triggerScenarios":"Calling `pypi package <name>` where the PyPI endpoint `${PYPI_BASE}/pypi/<name>/json` returns 200 but the body lacks `info` or `info.name` — e.g. an intermediary/proxy returning an empty or HTML 200 body, or a shadowed/malformed package record.","commonSituations":"Corporate proxies or captive portals returning 200 with HTML; PyPI incidents serving partial JSON; package names that exist on a mirror but not on pypi.org; DNS hijacking responses.","solutions":["Re-run the command to rule out a transient PyPI/proxy issue","Verify the package exists by opening https://pypi.org/pypi/<name>/json directly in a browser or curl","Check for network interference (proxy, VPN, corporate firewall) that could replace the response body","Confirm no typo in the package name and use the canonical PyPI distribution name"],"exampleFix":"// before (shell)\npypi package my-pkg\n// after (verify endpoint manually first)\ncurl -s https://pypi.org/pypi/requests/json | jq '.info.name'","handlingStrategy":"try-catch","validationCode":"const res = await fetch(`https://pypi.org/pypi/${name}/json`);\nconst body = await res.json();\nif (!body?.info?.name) console.warn('PyPI metadata unavailable');","typeGuard":"function hasPypiInfo(b) { return b != null && typeof b === 'object' && b.info != null && typeof b.info.name === 'string' && b.info.name.length > 0; }","tryCatchPattern":"try {\n  const pkg = await pypiPackage(name);\n} catch (e) {\n  if (/no metadata/i.test(e.message)) {\n    // fall back to cached data or notify user the API payload was empty\n  } else throw e;\n}","preventionTips":["Verify the endpoint returns valid JSON metadata before scripting against it","Watch PyPI status for incidents affecting the JSON API","Cache successful lookups so transient empty payloads don't break workflows"],"tags":["pypi","network","empty-response"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}