Hmbown/CodeWhale · error · Error
npm pack metadata did not include a filename: ${trimmed}
Error message
npm pack metadata did not include a filename: ${trimmed} What it means
parsePackJson() managed to JSON.parse the npm pack --json stdout, but the first entry had no `filename` field. npm's pack report entries normally carry id/name/version/filename; a JSON result without filename means an unexpected npm version or output shape reached the parser.
Source
Thrown at scripts/release/npm-wrapper-smoke.js:130
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");
const installDir = path.join(tempRoot, "install");
let keepTemp = process.env.DEEPSEEK_TUI_KEEP_SMOKE_DIR === "1";
let server;
try {View on GitHub (pinned to 8880682c63)
Solutions
- Read the trimmed stdout embedded in the error message - it shows exactly what npm printed
- Run the pack from the leaf package directory instead of a workspace root
- Upgrade npm to a current LTS release
- If stdout mixes log noise, make runCommand() keep stdout/stderr strictly separate
Example fix
// before
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;
// after - fall back to the tarball npm actually wrote into packDir
const first = Array.isArray(parsed) ? parsed[0] : parsed;
const filename = first?.filename || (await fsp.readdir(packDir)).find((f) => f.endsWith('.tgz'));
if (!filename) {
throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);
}
return filename; Defensive patterns
Strategy: type-guard
Validate before calling
const entries = (await fsp.readdir(packDir)).filter((f) => f.endsWith('.tgz'));
if (entries.length !== 1) {
throw new Error(`expected exactly one tarball in ${packDir}, found: ${entries.join(', ')}`);
} Type guard
function isPackMetadata(value) {
return (
typeof value === 'object' && value !== null &&
typeof value.filename === 'string' && value.filename.endsWith('.tgz')
);
}
const first = Array.isArray(parsed) ? parsed[0] : parsed;
if (!isPackMetadata(first)) {
throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);
} Prevention
- Run pack from leaf package dirs, not workspace roots
- Keep stdout free of interleaved log noise before parsing JSON
- Cross-check the reported filename against the .tgz actually written to pack-destination
When it happens
Trigger: `npm pack --json` emitting objects lacking `filename` - seen with some workspace setups where pack runs at a workspace root, or when extra log lines interleave with stdout so the parsed first element is not a pack entry.
Common situations: package.json with `workspaces` changing pack output; an npm fork or unusual version in CI; stdout polluted by notices so JSON.parse still succeeds but yields a foreign object.
Related errors
- npm pack did not return package metadata
- GitHub Release ${tag} returned invalid JSON: ${error.message
- GitHub Release ${tag} did not provide an asset inventory
- Cargo metadata is not valid JSON: {error}
- Cargo metadata root must be an object
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/1ee0e27ae2578378.
Report an issue: GitHub.