paperclipai/paperclip · error · Error
Evalbook requires the chat viewer. Run pnpm --filter…
Error message
Evalbook requires the chat viewer. Run pnpm --filter @paperclipai/paperclip-runner build:issue-thread first.
What it means
renderRunnerWorkflowWithCanonicalEvalbook requires the built chat viewer (dist-issue-thread/index.html) to bundle into the Evalbook, and throws this error when the viewer build output is absent. The script tells you the exact pnpm build command to produce it.
Solutions
- Run `pnpm --filter @paperclipai/paperclip-runner build:issue-thread` and retry
- If using a custom viewer location, ensure PAPERCLIP_EVAL_VIEWER_ROOT points at a build output containing index.html
- Verify dist-issue-thread/index.html exists after the build (ls dist-issue-thread)
- In CI, add the viewer build step before the evalbook render step
Example fix
// before node scripts/render-runner-workflow-evalbook.mjs ... // after pnpm --filter @paperclipai/paperclip-runner build:issue-thread && \ node scripts/render-runner-workflow-evalbook.mjs ...
Defensive patterns
Strategy: fallback
Validate before calling
await access(join(viewerRoot,'index.html')).catch(() => { throw new Error('Viewer missing; run pnpm --filter @paperclipai/paperclip-runner build:issue-thread'); }); Type guard
null
Try / catch
try { await renderRunnerWorkflowEvalbook(...); } catch (e) { if (e.message.includes('chat viewer')) { execSync('pnpm --filter @paperclipai/paperclip-runner build:issue-thread', { stdio: 'inherit' }); return renderRunnerWorkflowEvalbook(...); } throw e; } Prevention
- Add build:issue-thread to the evalbook pipeline/CI before rendering
- Never point PAPERCLIP_EVAL_VIEWER_ROOT at a source dir instead of a build output
- Verify index.html exists after builds in setup checks
When it happens
Trigger: Running the renderer before building @paperclipai/paperclip-runner's issue-thread viewer; a clean CI workspace where only `pnpm install` ran; PAPERCLIP_EVAL_VIEWER_ROOT pointing at a directory without index.html.
Common situations: Fresh clone followed directly by the evalbook script; switching branches where dist-issue-thread was gitignored and never rebuilt; a typo'd PAPERCLIP_EVAL_VIEWER_ROOT.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- runner_local_provider_artifact_missing
- Canonical Evalbook generator not found. Set…
- bundle retained a non-builtin import
- Evalbook attempt identity is empty
- Expected @ , received @
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/7fb94d75c660b10e.
Report an issue: GitHub.
Appendix: source
Thrown at packages/paperclip-runner/scripts/render-runner-workflow-evalbook.mjs:317
);
});
});
}
export async function renderRunnerWorkflowWithCanonicalEvalbook({
packageRoot,
outputDirectory,
report,
caseForId,
environment = process.env,
}) {
const program = await resolveCanonicalEvalProgram(packageRoot, environment);
const viewerRoot = resolve(
environment.PAPERCLIP_EVAL_VIEWER_ROOT ??
resolve(packageRoot, "dist-issue-thread"),
);
await access(resolve(viewerRoot, "index.html")).catch(() => {
throw new Error(
"Evalbook requires the chat viewer. Run pnpm --filter @paperclipai/paperclip-runner build:issue-thread first.",
);
});
const runsRoot = resolve(outputDirectory, "evalbook-runs");
await rm(runsRoot, { recursive: true, force: true });
const attempts = await writeRunnerWorkflowEvalbookAttempts({
report,
runsRoot,
caseForId,
});
await Promise.all([
rm(resolve(outputDirectory, "attempts"), { recursive: true, force: true }),
rm(resolve(outputDirectory, "tests"), { recursive: true, force: true }),
rm(resolve(outputDirectory, "index.html"), { force: true }),
rm(resolve(outputDirectory, "latest.html"), { force: true }),
rm(resolve(outputDirectory, "live-report.html"), { force: true }),
rm(resolve(outputDirectory, "deterministic-report.html"), { force: true }),
]);View on GitHub (pinned to 01ad858492)