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

  1. Run the call redaction pass that replaces each call.result with { outcome, detail: 'Tool payload withheld from public replay.' }.
  2. Diff the offending call record against the redaction code path to see why the raw detail survived.
  3. 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

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


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