{"record":{"id":"1ee0e27ae2578378","repo":"Hmbown/CodeWhale","slug":"npm-pack-metadata-did-not-include-a-filename-tr","errorCode":null,"errorMessage":"npm pack metadata did not include a filename: ${trimmed}","messagePattern":"npm pack metadata did not include a filename: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/npm-wrapper-smoke.js","lineNumber":130,"sourceCode":"    server.listen(0, \"127.0.0.1\", () => {\n      const address = server.address();\n      resolve({\n        baseUrl: `http://127.0.0.1:${address.port}/`,\n        server,\n      });\n    });\n  });\n}\n\nfunction parsePackJson(stdout) {\n  const trimmed = stdout.trim();\n  if (!trimmed) {\n    throw new Error(\"npm pack did not return package metadata\");\n  }\n  const parsed = JSON.parse(trimmed);\n  const first = Array.isArray(parsed) ? parsed[0] : parsed;\n  if (!first || !first.filename) {\n    throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);\n  }\n  return first.filename;\n}\n\nasync function main() {\n  const tempRoot = await fsp.mkdtemp(path.join(os.tmpdir(), \"codewhale-npm-smoke-\"));\n  const suppliedAssetsDir = String(\n    process.env.CODEWHALE_SMOKE_ASSETS_DIR || \"\",\n  ).trim();\n  const releaseAssetsDir = suppliedAssetsDir\n    ? path.resolve(suppliedAssetsDir)\n    : path.join(tempRoot, \"release-assets\");\n  const packDir = path.join(tempRoot, \"pack\");\n  const installDir = path.join(tempRoot, \"install\");\n  let keepTemp = process.env.DEEPSEEK_TUI_KEEP_SMOKE_DIR === \"1\";\n  let server;\n\n  try {","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/npm-wrapper-smoke.js#L112-L148","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst first = Array.isArray(parsed) ? parsed[0] : parsed;\nif (!first || !first.filename) {\n  throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);\n}\nreturn first.filename;\n\n// after - fall back to the tarball npm actually wrote into packDir\nconst first = Array.isArray(parsed) ? parsed[0] : parsed;\nconst filename = first?.filename || (await fsp.readdir(packDir)).find((f) => f.endsWith('.tgz'));\nif (!filename) {\n  throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);\n}\nreturn filename;","handlingStrategy":"type-guard","validationCode":"const entries = (await fsp.readdir(packDir)).filter((f) => f.endsWith('.tgz'));\nif (entries.length !== 1) {\n  throw new Error(`expected exactly one tarball in ${packDir}, found: ${entries.join(', ')}`);\n}","typeGuard":"function isPackMetadata(value) {\n  return (\n    typeof value === 'object' && value !== null &&\n    typeof value.filename === 'string' && value.filename.endsWith('.tgz')\n  );\n}\nconst first = Array.isArray(parsed) ? parsed[0] : parsed;\nif (!isPackMetadata(first)) {\n  throw new Error(`npm pack metadata did not include a filename: ${trimmed}`);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["npm","release","packaging","json"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}