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
- Delete or rename the existing output directory before rerunning
- Choose a new --output path (or include the revision/timestamp in the path so it is unique)
- 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
- Make output paths unique per run (include revision/timestamp)
- Clean stale outputs before reruns
- Check for leftover partial outputs from failed runs
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
- native_runner_authority_archive_unsafe
- Invalid ${name} JSON: ${err instanceof Error ? err.message :
- Challenge secret is required. Pass --token or --token-env.
- Cannot build API path with an empty path segment.
- Plugin UI directory not found
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b383281144a731a3.
Report an issue: GitHub.