{"record":{"id":"fc13d61542941346","repo":"headroomlabs-ai/headroom","slug":"expected-npm-pack-to-produce-tarballpath","errorCode":null,"errorMessage":"Expected npm pack to produce ${tarballPath}","messagePattern":"Expected npm pack to produce (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/build_npm_release_assets.mjs","lineNumber":157,"sourceCode":"  const packageJsonPath = path.join(openClawDir, \"package.json\");\n  const pkg = readJson(packageJsonPath);\n  pkg.dependencies = pkg.dependencies || {};\n  pkg.dependencies[\"headroom-ai\"] = spec;\n  writeJson(packageJsonPath, pkg);\n}\n\nfunction rewriteOpenClawLocalDependency(sdkTarballPath) {\n  rewriteOpenClawDependency(relativeFileSpec(openClawDir, sdkTarballPath));\n}\n\nfunction rewriteOpenClawReleaseDependency() {\n  rewriteOpenClawDependency(`^${version}`);\n}\n\nfunction assertTarballBuilt(name) {\n  const tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);\n  if (!existsSync(tarballPath)) {\n    throw new Error(`Expected npm pack to produce ${tarballPath}`);\n  }\n  return tarballPath;\n}\n\ntry {\n  ensureEmptyAssetsDir();\n\n  if (!flags.has(\"--skip-install\")) {\n    runNpm([\"ci\"], sdkDir);\n  }\n  runNpm([\"run\", \"build\"], sdkDir);\n  runNpm([\"version\", version, \"--no-git-tag-version\", \"--allow-same-version\"], sdkDir);\n  runNpm([\"pack\", \"--pack-destination\", assetsDir], sdkDir);\n  const sdkTarballPath = assertTarballBuilt(\"headroom-ai\");\n\n  rewriteOpenClawLocalDependency(sdkTarballPath);\n  if (!flags.has(\"--skip-install\")) {\n    runNpm(","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/scripts/build_npm_release_assets.mjs#L139-L175","documentation":"Thrown by assertTarballBuilt() after the script runs `npm pack` for the SDK package. It expects a tarball named `<name>-<version>.tgz` in the assets directory and throws when that exact file is absent. The build treats a missing tarball as a hard failure because downstream steps (dependency rewrites, verification) all consume that file.","triggerScenarios":"Running scripts/build_npm_release_assets.mjs with a version that does not match the version `npm version` stamped into package.json; a scoped package whose tarball filename uses the flattened form (`@scope/name` becomes `scope-name-x.y.z.tgz`) while `name` is looked up unflattened; `npm pack` writing to a different destination than assetsDir; or `npm pack` failing quietly (runNpm not checking stderr).","commonSituations":"Version drift between the CLI argument and package.json; rerunning the script after a partially failed run left assetsDir in a bad state; npm config (`pack-destination`) or workspaces changing where the tarball lands; package.json `name` edited between runs.","solutions":["List the assets directory and compare the actual tarball filename with `<name>-<version>.tgz`; if the version differs, rerun the script with the version npm stamped (`npm pkg get version` in the SDK dir).","If the package is scoped, confirm the lookup uses the flattened filename npm pack produces (scope-name-version.tgz) or pass the flattened name to assertTarballBuilt.","Confirm the `npm pack` invocation includes `--pack-destination <assetsDir>` and that runNpm checks a nonzero exit code.","Delete the assets directory (ensureEmptyAssetsDir recreates it) and rerun the full script so version stamping and packing happen in one pass."],"exampleFix":"// before\nconst tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);\nif (!existsSync(tarballPath)) {\n  throw new Error(`Expected npm pack to produce ${tarballPath}`);\n}\n\n// after: fall back to the flattened scoped name npm pack actually emits\nconst packedName = name.replace(/^@/, \"\").replace(\"/\", \"-\");\nlet tarballPath = path.join(assetsDir, `${packedName}-${version}.tgz`);\nif (!existsSync(tarballPath)) {\n  tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);\n}\nif (!existsSync(tarballPath)) {\n  throw new Error(`Expected npm pack to produce ${tarballPath}`);\n}","handlingStrategy":"validation","validationCode":"import { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\n\nfunction findPackedTarball(assetsDir, name, version) {\n  const candidates = [\n    `${name}-${version}.tgz`,\n    `${name.replace(/^@/, \"\").replace(\"/\", \"-\")}-${version}.tgz`,\n  ];\n  for (const file of candidates) {\n    if (existsSync(path.join(assetsDir, file))) return path.join(assetsDir, file);\n  }\n  return null;\n}\n// call before assertTarballBuilt; log readdirSync(assetsDir) when null","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always derive the version for the script from the same source npm stamps (`npm pkg get version`), never a hand-typed argument.","Run the script end-to-end (install → build → version → pack → assert) instead of resuming mid-way.","Start from the empty assets dir the script creates; never point it at a reused directory."],"tags":["npm","release","build","pack"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}