{"record":{"id":"15739416ecea9ab5","repo":"Hmbown/CodeWhale","slug":"npm-pack-did-not-return-package-metadata","errorCode":null,"errorMessage":"npm pack did not return package metadata","messagePattern":"npm pack did not return package metadata","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/npm-wrapper-smoke.js","lineNumber":125,"sourceCode":"    }\n  });\n\n  return new Promise((resolve, reject) => {\n    server.once(\"error\", reject);\n    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\");","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/npm-wrapper-smoke.js#L107-L143","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nconst pack = await runCommand('npm', ['pack', '--json', '--pack-destination', packDir], { capture: true, cwd: packageDir, env });\nconst tarball = path.join(packDir, parsePackJson(pack.stdout));\n\n// after - gate on npm major version first\nconst versionOut = await runCommand('npm', ['--version'], { capture: true });\nconst major = Number(versionOut.stdout.trim().split('.')[0]);\nif (!(major >= 7)) {\n  throw new Error(`npm >= 7 required for pack --json output, found ${versionOut.stdout.trim()}`);\n}\nconst pack = await runCommand('npm', ['pack', '--json', '--pack-destination', packDir], { capture: true, cwd: packageDir, env });\nconst tarball = path.join(packDir, parsePackJson(pack.stdout));","handlingStrategy":"validation","validationCode":"import { execFileSync } from 'node:child_process';\nconst [major] = execFileSync('npm', ['--version'], { encoding: 'utf8' }).trim().split('.').map(Number);\nif (!(major >= 7)) {\n  throw new Error(`npm >= 7 required for pack --json output, found ${major}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  tarball = path.join(packDir, parsePackJson(pack.stdout));\n} catch (err) {\n  console.error('npm stdout:', JSON.stringify(pack.stdout));\n  console.error('npm stderr:', pack.stderr);\n  throw err;\n}","preventionTips":["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"],"tags":["npm","release","ci","packaging"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}