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

  1. Read the trimmed stdout embedded in the error message - it shows exactly what npm printed
  2. Run the pack from the leaf package directory instead of a workspace root
  3. Upgrade npm to a current LTS release
  4. 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

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


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/1ee0e27ae2578378. Report an issue: GitHub.