Hmbown/CodeWhale · error · Error
npm pack did not return package metadata
Error message
npm pack did not return package metadata
What it means
Thrown by parsePackJson() in the npm wrapper smoke test after `npm pack --json --pack-destination <dir>` returned completely empty stdout. npm 7+ prints a JSON array of packed-tarball metadata to stdout; an empty string means that JSON report never arrived. The smoke script then cannot learn the .tgz filename it just built.
Source
Thrown at scripts/release/npm-wrapper-smoke.js:125
}
});
return new Promise((resolve, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", () => {
const address = server.address();
resolve({
baseUrl: `http://127.0.0.1:${address.port}/`,
server,
});
});
});
}
function parsePackJson(stdout) {
const trimmed = stdout.trim();
if (!trimmed) {
throw new Error("npm pack did not return package metadata");
}
const parsed = JSON.parse(trimmed);
const first = Array.isArray(parsed) ? parsed[0] : parsed;
if (!first || !first.filename) {
throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);
}
return first.filename;
}
async function main() {
const tempRoot = await fsp.mkdtemp(path.join(os.tmpdir(), "codewhale-npm-smoke-"));
const suppliedAssetsDir = String(
process.env.CODEWHALE_SMOKE_ASSETS_DIR || "",
).trim();
const releaseAssetsDir = suppliedAssetsDir
? path.resolve(suppliedAssetsDir)
: path.join(tempRoot, "release-assets");
const packDir = path.join(tempRoot, "pack");View on GitHub (pinned to 8880682c63)
Solutions
- Check `npm --version` in the same shell/CI image; upgrade to npm >= 7 (`npm i -g npm@latest` or use Node 16+)
- Run `npm pack --json --pack-destination /tmp/pack` by hand in the package directory and confirm the JSON array prints to stdout
- Inspect .npmrc and NPM_CONFIG_* env for loglevel/silent settings that suppress stdout
- Rerun the smoke script and read the retained workspace path printed on failure for clues
Example fix
// before
const pack = await runCommand('npm', ['pack', '--json', '--pack-destination', packDir], { capture: true, cwd: packageDir, env });
const tarball = path.join(packDir, parsePackJson(pack.stdout));
// after - gate on npm major version first
const versionOut = await runCommand('npm', ['--version'], { capture: true });
const major = Number(versionOut.stdout.trim().split('.')[0]);
if (!(major >= 7)) {
throw new Error(`npm >= 7 required for pack --json output, found ${versionOut.stdout.trim()}`);
}
const pack = await runCommand('npm', ['pack', '--json', '--pack-destination', packDir], { capture: true, cwd: packageDir, env });
const tarball = path.join(packDir, parsePackJson(pack.stdout)); Defensive patterns
Strategy: validation
Validate before calling
import { execFileSync } from 'node:child_process';
const [major] = execFileSync('npm', ['--version'], { encoding: 'utf8' }).trim().split('.').map(Number);
if (!(major >= 7)) {
throw new Error(`npm >= 7 required for pack --json output, found ${major}`);
} Try / catch
try {
tarball = path.join(packDir, parsePackJson(pack.stdout));
} catch (err) {
console.error('npm stdout:', JSON.stringify(pack.stdout));
console.error('npm stderr:', pack.stderr);
throw err;
} Prevention
- Pin Node/npm versions in CI to match the release requirements (npm >= 7)
- Assert toolchain versions in a preflight step before any pack-dependent script
- Keep runCommand() capture wired to both stdout and stderr for diagnostics
When it happens
Trigger: Running scripts/release/npm-wrapper-smoke.js with npm < 7 (no --json report), with npm configured silent (loglevel=silent / --silent), or in an environment where runCommand() only captures stdout while npm wrote its output elsewhere (e.g., output redirected or swallowed by a wrapper).
Common situations: CI images pinned to legacy Node 14/npm 6; a local .npmrc with loglevel=quiet; a broken package.json making npm bail with output only on stderr while exit codes are ignored.
Related errors
- npm pack metadata did not include a filename: ${trimmed}
- ${label} does not match the authoritative inventory; missing
- Release asset directory must be flat; found: ${nonFiles.map(
- Downloaded release artifacts are missing ${name} at ${source
- Downloaded release artifact must be a regular file: ${source
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/15739416ecea9ab5.
Report an issue: GitHub.