paperclipai/paperclip · error · Error

Report refresh output must be a new directory

Error message

Report refresh output must be a new directory

What it means

refreshProtocolEvalReport requires the outputRoot directory to not exist yet (checked via lstat) so each refresh produces a pristine, non-clobbered report directory. The error means a file or directory already exists at the output path.

Source

Thrown at packages/paperclip-runner/scripts/refresh-runner-protocol-eval-report.mjs:23

import { mkdir, readFile, writeFile, lstat, readdir } from "node:fs/promises";
import { join, resolve } from "node:path";
import { sanitizeProtocolEvalRuns } from "./runner-protocol-eval-campaign.mjs";
import { validatePublicProtocolEvalReport } from "./publish-runner-protocol-eval-history.mjs";
import { sumAttemptCosts } from "./runner-protocol-eval-metrics.mjs";

export async function refreshProtocolEvalReport({
  sourceRoot,
  evalsRoot,
  viewerRoot,
  outputRoot,
  revision,
  selection,
  renderedAt = new Date().toISOString(),
}) {
  if (!/^[a-z0-9][a-z0-9-]{0,39}$/.test(revision ?? ""))
    throw new Error("A safe, unique --revision is required");
  if (await lstat(outputRoot).catch(() => null))
    throw new Error("Report refresh output must be a new directory");
  const campaign = JSON.parse(
    await readFile(join(sourceRoot, "campaign.json"), "utf8"),
  );
  if (!/^gha-[1-9][0-9]*-[1-9][0-9]*$/.test(campaign.campaignId ?? ""))
    throw new Error("Expected an original Actions campaign");
  const program = join(
    evalsRoot,
    "evals/paperclip-runner/tools/eval_program.py",
  );
  const rendererDigest = createHash("sha256")
    .update(await readFile(program))
    .digest("hex");
  await mkdir(outputRoot, { recursive: true });
  const runsRoot = join(outputRoot, "public-runs");
  const reportRoot = join(outputRoot, "report");
  await sanitizeProtocolEvalRuns({
    runsRoot: join(sourceRoot, "runs"),
    publicRunsRoot: runsRoot,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Delete or rename the existing output directory before rerunning
  2. Choose a new --output path (or include the revision/timestamp in the path so it is unique)
  3. If the prior run is known-good and you truly want to overwrite, move it aside instead of letting the script overwrite

Example fix

// before
node refresh-runner-protocol-eval-report.mjs --output out/report
// after
rm -rf out/report && node refresh-runner-protocol-eval-report.mjs --output out/report
Defensive patterns

Strategy: validation

Validate before calling

const exists = await lstat(outputRoot).catch(() => null); if (exists) throw new Error('Output path already exists: ' + outputRoot);

Type guard

null

Try / catch

try { await refreshProtocolEvalReport(opts); } catch (e) { if (e.message === 'Report refresh output must be a new directory') console.error('rm -rf ' + opts.outputRoot + ' or pick a new path'); throw e; }

Prevention

When it happens

Trigger: Re-running the script with the same --output directory as a previous run; a leftover/partial output directory from a failed run; outputRoot defaulting into an existing path like the repo's dist folder.

Common situations: Retry of a failed CI job reusing a cached workspace with the old output present; local iteration where the developer reruns the command without deleting the previous output.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/b383281144a731a3. Report an issue: GitHub.