{"record":{"id":"b383281144a731a3","repo":"paperclipai/paperclip","slug":"report-refresh-output-must-be-a-new-directory","errorCode":null,"errorMessage":"Report refresh output must be a new directory","messagePattern":"Report refresh output must be a new directory","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/refresh-runner-protocol-eval-report.mjs","lineNumber":23,"sourceCode":"import { mkdir, readFile, writeFile, lstat, readdir } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { sanitizeProtocolEvalRuns } from \"./runner-protocol-eval-campaign.mjs\";\nimport { validatePublicProtocolEvalReport } from \"./publish-runner-protocol-eval-history.mjs\";\nimport { sumAttemptCosts } from \"./runner-protocol-eval-metrics.mjs\";\n\nexport async function refreshProtocolEvalReport({\n  sourceRoot,\n  evalsRoot,\n  viewerRoot,\n  outputRoot,\n  revision,\n  selection,\n  renderedAt = new Date().toISOString(),\n}) {\n  if (!/^[a-z0-9][a-z0-9-]{0,39}$/.test(revision ?? \"\"))\n    throw new Error(\"A safe, unique --revision is required\");\n  if (await lstat(outputRoot).catch(() => null))\n    throw new Error(\"Report refresh output must be a new directory\");\n  const campaign = JSON.parse(\n    await readFile(join(sourceRoot, \"campaign.json\"), \"utf8\"),\n  );\n  if (!/^gha-[1-9][0-9]*-[1-9][0-9]*$/.test(campaign.campaignId ?? \"\"))\n    throw new Error(\"Expected an original Actions campaign\");\n  const program = join(\n    evalsRoot,\n    \"evals/paperclip-runner/tools/eval_program.py\",\n  );\n  const rendererDigest = createHash(\"sha256\")\n    .update(await readFile(program))\n    .digest(\"hex\");\n  await mkdir(outputRoot, { recursive: true });\n  const runsRoot = join(outputRoot, \"public-runs\");\n  const reportRoot = join(outputRoot, \"report\");\n  await sanitizeProtocolEvalRuns({\n    runsRoot: join(sourceRoot, \"runs\"),\n    publicRunsRoot: runsRoot,","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/refresh-runner-protocol-eval-report.mjs#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nnode refresh-runner-protocol-eval-report.mjs --output out/report\n// after\nrm -rf out/report && node refresh-runner-protocol-eval-report.mjs --output out/report","handlingStrategy":"validation","validationCode":"const exists = await lstat(outputRoot).catch(() => null); if (exists) throw new Error('Output path already exists: ' + outputRoot);","typeGuard":"null","tryCatchPattern":"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; }","preventionTips":["Make output paths unique per run (include revision/timestamp)","Clean stale outputs before reruns","Check for leftover partial outputs from failed runs"],"tags":["filesystem","idempotency","directory"],"backgroundTag":"file-already-exists","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}