headroomlabs-ai/headroom · error · Error

Assets directory must be empty to avoid stale tarballs: ${as

Error message

Assets directory must be empty to avoid stale tarballs: ${assetsDir}

What it means

The release asset script deliberately requires the assets output directory to be empty before building, so that no tarballs from a previous (possibly different-version) run can leak into the release. ensureEmptyAssetsDir() creates the directory if needed, then throws if it contains anything at all. This is a self-imposed guard against publishing stale artifacts.

Source

Thrown at scripts/build_npm_release_assets.mjs:113

}

function runNode(args, cwd) {
  run(process.execPath, args, cwd);
}

function readJson(filePath) {
  return JSON.parse(readFileSync(filePath, "utf8"));
}

function writeJson(filePath, data) {
  writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
}

function ensureEmptyAssetsDir() {
  mkdirSync(assetsDir, { recursive: true });
  const existing = readdirSync(assetsDir);
  if (existing.length > 0) {
    throw new Error(
      `Assets directory must be empty to avoid stale tarballs: ${assetsDir}`,
    );
  }
}

function restoreTrackedFiles() {
  for (const [filePath, contents] of snapshots.entries()) {
    if (contents === null) {
      rmSync(filePath, { force: true });
    } else {
      mkdirSync(path.dirname(filePath), { recursive: true });
      writeFileSync(filePath, contents, "utf8");
    }
  }
}

function relativeFileSpec(fromDir, targetPath) {
  let relativePath = path.relative(fromDir, targetPath).split(path.sep).join("/");

View on GitHub (pinned to 322425c43b)

Solutions

  1. Delete the directory contents and rerun: rm -rf <assetsDir> (the script recreates it)
  2. In CI, ensure the checkout/workspace cache does not persist the assets directory between jobs
  3. If artifacts there are precious, move them elsewhere before rerunning instead of deleting

Example fix

# before
node scripts/build_npm_release_assets.mjs  # throws: assets dir not empty

# after
rm -rf release-assets/  # or whatever assetsDir the script prints
node scripts/build_npm_release_assets.mjs
Defensive patterns

Strategy: validation

Validate before calling

import { readdirSync, rmSync } from "node:fs";

// Precheck before running the release script
const entries = readdirSync(assetsDir);
if (entries.length > 0) {
  throw new Error(
    `Assets dir not empty (${entries.length} files) — run: rm -rf ${assetsDir}`
  );
}

Type guard

import { readdirSync } from "node:fs";

function isAssetsDirClean(dir: string): boolean {
  return readdirSync(dir).length === 0;
}

Prevention

When it happens

Trigger: Running scripts/build_npm_release_assets.mjs when the assets directory already has files — a previous aborted/partial run, manual test builds dropped there, or a CI workspace/cache that persists the directory between jobs.

Common situations: Rerunning the script after a late-stage failure left partial tarballs; CI workspace caching that includes the assets dir; committing or copying earlier release artifacts into the output folder.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/2c8f507c203fd65a. Report an issue: GitHub.