jackwener/OpenCLI · error · EmptyResultError

pypi package

Error message

pypi package

What it means

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.

Source

Thrown at clis/pypi/package.js:48

    name: 'package',
    access: 'read',
    description: 'Single PyPI package metadata (latest version, license, homepage, classifiers)',
    domain: 'pypi.org',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'name', positional: true, required: true, help: 'PyPI package name (e.g. "requests", "pandas")' },
    ],
    columns: [
        'name', 'latestVersion', 'summary', 'author', 'license', 'homepage', 'repository',
        'requiresPython', 'keywords', 'releases', 'firstReleased', 'lastReleased', 'url',
    ],
    func: async (args) => {
        const name = requirePackageName(args.name);
        const body = await pypiFetch(`${PYPI_BASE}/pypi/${encodeURIComponent(name)}/json`, `pypi package ${name}`);
        const info = body?.info;
        if (!info || !info.name) {
            throw new EmptyResultError('pypi package', `PyPI returned no metadata for "${name}".`);
        }
        const releases = body?.releases ?? {};
        const releaseVersions = Object.keys(releases).filter((v) => Array.isArray(releases[v]) && releases[v].length > 0);
        // earliest / latest release timestamps from the upload_time fields
        let firstReleased = '';
        let lastReleased = '';
        for (const v of releaseVersions) {
            for (const file of releases[v]) {
                const t = String(file?.upload_time ?? '').slice(0, 10);
                if (!t) continue;
                if (!firstReleased || t < firstReleased) firstReleased = t;
                if (!lastReleased || t > lastReleased) lastReleased = t;
            }
        }
        return [{
            name: String(info.name),
            latestVersion: String(info.version ?? ''),
            summary: String(info.summary ?? ''),

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command to rule out a transient PyPI/proxy issue
  2. Verify the package exists by opening https://pypi.org/pypi/<name>/json directly in a browser or curl
  3. Check for network interference (proxy, VPN, corporate firewall) that could replace the response body
  4. Confirm no typo in the package name and use the canonical PyPI distribution name

Example fix

// before (shell)
pypi package my-pkg
// after (verify endpoint manually first)
curl -s https://pypi.org/pypi/requests/json | jq '.info.name'
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch(`https://pypi.org/pypi/${name}/json`);
const body = await res.json();
if (!body?.info?.name) console.warn('PyPI metadata unavailable');

Type guard

function hasPypiInfo(b) { return b != null && typeof b === 'object' && b.info != null && typeof b.info.name === 'string' && b.info.name.length > 0; }

Try / catch

try {
  const pkg = await pypiPackage(name);
} catch (e) {
  if (/no metadata/i.test(e.message)) {
    // fall back to cached data or notify user the API payload was empty
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/c0e202b25a6b488a. Report an issue: GitHub.