paperclipai/paperclip · error · Error

Public replay contains unprojected evidence

Error message

Public replay contains unprojected evidence

What it means

Thrown by validatePublicChatPayload in the public eval viewer script. The public replay payload is supposed to be a projected view where the 'parity' evidence section (and similar sections) are either absent or empty arrays, since raw evidence must not leak into a public artifact. If a projected section still contains items, the projection step was skipped or buggy, so the validator throws.

Source

Thrown at packages/paperclip-runner/scripts/public-eval-viewer.mjs:181

        visit(child, name);
      }
    }
  };
  visit(payload);
  for (const section of [
    "tools",
    "authorization",
    "control_plane",
    "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",

View on GitHub (pinned to 01ad858492)

Solutions

  1. Run the evidence projection step so evidence.parity (and all projected sections) are emitted as empty arrays before validation.
  2. Check the code that builds payload.view.evidence to ensure every section iterated here is cleared for public output.
  3. If the payload was edited by hand, remove the leaked parity evidence entries.

Example fix

// before
view.evidence.parity = internalParityResults;
// after
view.evidence.parity = []; // projected: public replay carries no parity evidence
Defensive patterns

Strategy: validation

Validate before calling

const projected = ['parity'].every(s => Array.isArray(view.evidence?.[s]) && view.evidence[s].length === 0);
if (!projected) throw new Error('evidence sections must be empty in public payload');

Type guard

function isProjectedEvidence(e) { return Array.isArray(e?.parity) && e.parity.length === 0; }

Prevention

When it happens

Trigger: Calling validatePublicChatPayload with a payload whose payload.view.evidence.parity (or another iterated section) is a non-empty array; also triggered when the section is not an array at all.

Common situations: Regenerating a public replay without running the evidence-projection/redaction step; hand-editing the JSON and pasting internal evidence; a code change adding a new evidence section that the projector does not clear.

Related errors


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