paperclipai/paperclip · critical · Error
Public replay contains a private session identity
Error message
Public replay contains a private session identity
What it means
The visit() walker in validatePublicChatPayload() recursively scans every string value in the payload. Any string stored under a key ending in sessionId or providerSessionId (case-insensitive) must be exactly "public-report", "unknown", or "redacted"; anything else means an internal session identifier survived projection, and "Public replay contains a private session identity" is thrown.
Source
Thrown at packages/paperclip-runner/scripts/public-eval-viewer.mjs:146
"tools calls authorization control_plane runner state traceability parity",
);
for (const check of payload.checks) {
fields(
check,
"id kind passed detail evidenceRefs title description definition anchor",
);
fields(check.definition, "id kind");
fields(check.anchor, "kind id");
if (check.evidenceRefs.length)
throw new Error("Public replay contains raw evidence references");
}
const visit = (value, key = "") => {
if (typeof value === "string") {
if (
/(?:sessionId|providerSessionId)$/i.test(key) &&
!["public-report", "unknown", "redacted"].includes(value)
)
throw new Error("Public replay contains a private session identity");
for (const pattern of SECRET_TEXT) {
pattern.lastIndex = 0;
if (pattern.test(value))
throw new Error(
"Public replay contains credential or private reference material",
);
}
} else if (value && typeof value === "object") {
for (const [name, child] of Object.entries(value)) {
if (
/^(?:managedProfile|acpxProfile|providerTrace|mockState|stateHistory|trace|environment|env|apiKey|accessToken|password|secret)$/i.test(
name,
) &&
child != null
)
throw new Error("Public replay contains a private field");
visit(child, name);
}View on GitHub (pinned to 01ad858492)
Solutions
- Redact every sessionId/providerSessionId value in the projection to "public-report" (or "unknown"/"redacted") before validation.
- Locate the offending key path and extend the projector to redact that nested section, not just the top-level view.
- Confirm the projector's redaction matches the allowed values exactly (case-sensitive: "public-report", "unknown", "redacted").
- Regenerate the payload with the fixed projector and revalidate.
Example fix
// before
item: { id, sessionId: run.providerSessionId },
// after
item: { id, sessionId: "redacted" }, Defensive patterns
Strategy: validation
Validate before calling
const SESSION_OK = new Set(["public-report", "unknown", "redacted"]);
const walk = (v, key = "") => typeof v === "string"
? (/(?:sessionId|providerSessionId)$/i.test(key) && !SESSION_OK.has(v) && console.warn("unredacted session id at", key))
: v && typeof v === "object" && Object.entries(v).forEach(([k, c]) => walk(c, k));
walk(payload); Type guard
const sessionIdsRedacted = (payload) => { let ok = true; const walk = (v, k = "") => { if (typeof v === "string") { if (/(?:sessionId|providerSessionId)$/i.test(k) && !["public-report","unknown","redacted"].includes(v)) ok = false; } else if (v && typeof v === "object") Object.entries(v).forEach(([n, c]) => walk(c, n)); }; walk(payload); return ok; }; Try / catch
try {
validatePublicChatPayload(payload);
} catch (err) {
if (err.message === "Public replay contains a private session identity") {
throw new Error("A nested sessionId survived projection; redact all sessionId/providerSessionId values before publishing");
}
throw err;
} Prevention
- Redact session IDs at the point of projection, not at publish time
- Use a single redaction helper for every new payload section that could carry IDs
- Test the walker against deeply nested fixtures containing real-looking session IDs
- Keep the allowed sentinel values (public-report/unknown/redacted) in a shared constant
When it happens
Trigger: Calling validatePublicChatPayload with a payload containing any nested {sessionId: "<real-id>"} or {providerSessionId: "..."} — e.g. turns, evidence calls, or run blocks that retained their original session IDs instead of redacting to "public-report"/"unknown"/"redacted".
Common situations: A newly added payload section (e.g. a new turn item or call field) includes raw sessionId and the projector doesn't touch it; the redaction allowlist words were changed; nested objects deep in the tree bypassed the projector's top-level redaction.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Public replay contains private provider metadata
- Public replay contains raw evidence references
- Public replay contains a private field
- Public replay contains credential or private reference mater
- sandbox runtime asset key is not a simple path segment: ${ke
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/cf9f958644166f25.
Report an issue: GitHub.