paperclipai/paperclip · error · Error
Public replay contains raw call evidence
Error message
Public replay contains raw call evidence
What it means
Thrown by validatePublicChatPayload when a call entry in payload.view.evidence.calls has a result.detail other than the exact sentinel string 'Tool payload withheld from public replay.'. Call evidence in public replays must be stubbed with this redaction marker; any other detail means raw tool output leaked into the public artifact.
Source
Thrown at packages/paperclip-runner/scripts/public-eval-viewer.mjs:190
"runner",
"state",
"traceability",
"parity",
]) {
if (
!Array.isArray(payload.view.evidence?.[section]) ||
payload.view.evidence[section].length
)
throw new Error("Public replay contains unprojected evidence");
}
for (const call of payload.view.evidence.calls) {
fields(
call,
"id turnId operationId version providerRequest dispatchedCommand outcome result redactions threadAnchorId",
);
fields(call.result, "outcome detail");
if (call.result.detail !== "Tool payload withheld from public replay.")
throw new Error("Public replay contains raw call evidence");
}
for (const turn of payload.view.turns ?? []) {
fields(turn, "id ordinal mode toolCallCount at stoppedByUser items");
for (const item of turn.items ?? []) {
if (
![
"user_message",
"agent_message",
"tool_activity",
"system_notice",
].includes(item.kind)
)
throw new Error("Public replay contains an unprojected item");
const shapes = {
user_message: "kind id at author body streaming",
agent_message: "kind id at author body streaming",
tool_activity:
"kind id at operationId status summary input result evidenceRef",View on GitHub (pinned to 01ad858492)
Solutions
- Run the call redaction pass that replaces each call.result with { outcome, detail: 'Tool payload withheld from public replay.' }.
- Diff the offending call record against the redaction code path to see why the raw detail survived.
- Regenerate the public replay from the internal run instead of editing it manually.
Example fix
// before
call.result = { outcome: 'ok', detail: rawToolOutput };
// after
call.result = { outcome: 'ok', detail: 'Tool payload withheld from public replay.' }; Defensive patterns
Strategy: type-guard
Validate before calling
if (calls.some(c => c.result?.detail !== 'Tool payload withheld from public replay.')) throw new Error('raw call evidence present'); Type guard
function isRedactedCall(c) { return c?.result?.detail === 'Tool payload withheld from public replay.'; } Try / catch
try { validatePublicChatPayload(payload); } catch (e) { if (e.message.includes('raw call evidence')) { console.error('call redaction step was skipped'); process.exit(1); } throw e; } Prevention
- Make call redaction an explicit pipeline stage that runs before serialization.
- Assert the sentinel detail string in tests for every generated call record.
- Keep the sentinel constant shared between producer and validator.
When it happens
Trigger: Validating a payload where any view.evidence.calls[i].result.detail is not exactly the withheld-payload sentinel, or where result fields are missing/extra relative to the allowed 'outcome detail' shape.
Common situations: Building the public view without running the call redaction pass; copying internal call records (with real tool output) into the public JSON; a redaction change renaming the sentinel string.
Related errors
- Public replay contains a raw tool payload
- sandbox runtime asset key is not a simple path segment: ${ke
- Invalid GitHub launcher run ID
- Unexpected trusted viewer asset
- Public attempt must contain the read-only public chat projec
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b1acecf13107f236.
Report an issue: GitHub.