jackwener/OpenCLI · error · CommandExecutionError
packagist package returned no "package" object for ${full}.
Error message
packagist package returned no "package" object for ${full}. What it means
Packagist's /packages/<vendor>/<name>.json endpoint responded, but the JSON body had no usable `package` object (missing, null, or not an object). Thrown as a CommandExecutionError because it indicates the response shape differs from what the CLI expects.
Source
Thrown at clis/packagist/package.js:28
cli({
site: 'packagist',
name: 'package',
access: 'read',
description: 'Fetch a Packagist package\'s metadata (version, downloads, license, repo, GitHub stars)',
domain: 'packagist.org',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'name', positional: true, required: true, help: 'Composer package "<vendor>/<package>" (e.g. "symfony/console", "monolog/monolog")' },
],
columns: ['package', 'version', 'releasedAt', 'license', 'description', 'repository', 'githubStars', 'favers', 'downloads', 'monthlyDownloads', 'dailyDownloads', 'url'],
func: async (args) => {
const { full } = requirePackageName(args.name);
const url = `${PACKAGIST_BASE}/packages/${full}.json`;
const body = await packagistFetch(url, 'packagist package');
const pkg = body?.package;
if (!pkg || typeof pkg !== 'object') {
throw new CommandExecutionError(`packagist package returned no "package" object for ${full}.`);
}
const versionKey = pickStableVersion(pkg.versions);
const versionEntry = versionKey ? pkg.versions?.[versionKey] : null;
const license = Array.isArray(versionEntry?.license) ? versionEntry.license.filter(Boolean).join(', ') : '';
const downloads = pkg.downloads ?? {};
return [{
package: String(pkg.name ?? full).trim(),
version: versionKey ? String(versionKey) : '',
releasedAt: trimDate(versionEntry?.time),
license,
description: String(pkg.description ?? '').trim(),
repository: String(pkg.repository ?? '').trim(),
githubStars: pkg.github_stars != null ? Number(pkg.github_stars) : null,
favers: pkg.favers != null ? Number(pkg.favers) : null,
downloads: downloads.total != null ? Number(downloads.total) : null,
monthlyDownloads: downloads.monthly != null ? Number(downloads.monthly) : null,
dailyDownloads: downloads.daily != null ? Number(downloads.daily) : null,
url: `https://packagist.org/packages/${full}`,View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw response body from `${PACKAGIST_BASE}/packages/${full}.json` to see what was actually returned
- Verify the package exists: open the same URL or https://packagist.org/packages/<vendor>/<name> in a browser
- Update the CLI — Packagist occasionally adjusts its JSON schema
- Confirm packagistFetch isn't swallowing error statuses and returning a non-package body
Example fix
// before
const pkg = body?.package;
if (!pkg) throw new Error('no package');
// after
const pkg = body?.package ?? body?.['package'] ?? null;
if (!pkg || typeof pkg !== 'object') {
console.error('Unexpected Packagist payload:', JSON.stringify(body).slice(0, 300));
throw new Error('no package object');
} Defensive patterns
Strategy: validation
Validate before calling
const url = `https://repo.packagist.org/p2/${vendor}/${name}.json`;
const ok = await fetch(url).then(r => r.ok).catch(() => false);
if (!ok) throw new Error(`Package ${vendor}/${name} not found on Packagist`); Type guard
function isPackagistPackageBody(b) { return b != null && typeof b === 'object' && b.package != null && typeof b.package === 'object'; } Try / catch
try {
const info = await packagistPackage('vendor/name');
return info;
} catch (e) {
if (/no "package" object/.test(e.message)) {
console.error('Unexpected Packagist payload — check schema or package existence');
return null;
}
throw e;
} Prevention
- Validate vendor/name format before calling (lowercase, one slash)
- Check the package detail JSON in a browser when the CLI reports a shape error
- Keep the CLI current; Packagist metadata endpoints (p2) evolve
- Inspect the raw response body when the parsed shape is unexpected
When it happens
Trigger: `packagist package` fetched `${PACKAGIST_BASE}/packages/${full}.json` after requirePackageName parsed the name; the response JSON parsed but `body.package` was absent or not an object — e.g. Packagist changed its schema or served an error page as JSON.
Common situations: Packagist API schema change; the fetch layer returning an error envelope (e.g. {status:'error'}) instead of package data; a cached/proxied response missing the package key; querying a package that exists in search but whose detail endpoint returns an empty document.
Related errors
- Bilibili user search returned malformed result for ${input}
- Ctrip flight API returned a malformed batchSearch payload
- Ctrip flight API returned an itinerary without an id
- ${label} returned JSON without result.status.@code
- eastmoney convertible returned malformed ${field} for ${bond
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e82831a0482e5e10.
Report an issue: GitHub.