headroomlabs-ai/headroom · error · Error
Expected npm pack to produce ${tarballPath}
Error message
Expected npm pack to produce ${tarballPath} What it means
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.
Source
Thrown at scripts/build_npm_release_assets.mjs:157
const packageJsonPath = path.join(openClawDir, "package.json");
const pkg = readJson(packageJsonPath);
pkg.dependencies = pkg.dependencies || {};
pkg.dependencies["headroom-ai"] = spec;
writeJson(packageJsonPath, pkg);
}
function rewriteOpenClawLocalDependency(sdkTarballPath) {
rewriteOpenClawDependency(relativeFileSpec(openClawDir, sdkTarballPath));
}
function rewriteOpenClawReleaseDependency() {
rewriteOpenClawDependency(`^${version}`);
}
function assertTarballBuilt(name) {
const tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);
if (!existsSync(tarballPath)) {
throw new Error(`Expected npm pack to produce ${tarballPath}`);
}
return tarballPath;
}
try {
ensureEmptyAssetsDir();
if (!flags.has("--skip-install")) {
runNpm(["ci"], sdkDir);
}
runNpm(["run", "build"], sdkDir);
runNpm(["version", version, "--no-git-tag-version", "--allow-same-version"], sdkDir);
runNpm(["pack", "--pack-destination", assetsDir], sdkDir);
const sdkTarballPath = assertTarballBuilt("headroom-ai");
rewriteOpenClawLocalDependency(sdkTarballPath);
if (!flags.has("--skip-install")) {
runNpm(View on GitHub (pinned to 322425c43b)
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.
Example fix
// before
const tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);
if (!existsSync(tarballPath)) {
throw new Error(`Expected npm pack to produce ${tarballPath}`);
}
// after: fall back to the flattened scoped name npm pack actually emits
const packedName = name.replace(/^@/, "").replace("/", "-");
let tarballPath = path.join(assetsDir, `${packedName}-${version}.tgz`);
if (!existsSync(tarballPath)) {
tarballPath = path.join(assetsDir, `${name}-${version}.tgz`);
}
if (!existsSync(tarballPath)) {
throw new Error(`Expected npm pack to produce ${tarballPath}`);
} Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, readdirSync } from "node:fs";
import path from "node:path";
function findPackedTarball(assetsDir, name, version) {
const candidates = [
`${name}-${version}.tgz`,
`${name.replace(/^@/, "").replace("/", "-")}-${version}.tgz`,
];
for (const file of candidates) {
if (existsSync(path.join(assetsDir, file))) return path.join(assetsDir, file);
}
return null;
}
// call before assertTarballBuilt; log readdirSync(assetsDir) when null Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- ${command} failed with exit code ${result.status ?? "unknown
- Assets directory must be empty to avoid stale tarballs: ${as
- tar failed for ${tarballPath}: ${result.stderr || result.std
- Invalid semantic version: {value}
- Unsupported bump level: {level}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/fc13d61542941346.
Report an issue: GitHub.