paperclipai/paperclip · error · Error
Unknown public chat payload field
Error message
Unknown public chat payload field
What it means
After the projection gate, validatePublicChatPayload() enforces a strict allowlist of top-level payload keys (attemptId, caseId, disposition, passed, checks, view, devtools, navigation, run, publication). If any other key is present — even an innocuous extra field — "Unknown public chat payload field" is thrown. This fail-closed check prevents newly added internal fields from leaking into public reports before being explicitly allowlisted.
Source
Thrown at packages/paperclip-runner/scripts/public-eval-viewer.mjs:83
payload.devtools !== null
)
throw new Error(
"Public attempt must contain the read-only public chat projection",
);
const allowed = new Set([
"attemptId",
"caseId",
"disposition",
"passed",
"checks",
"view",
"devtools",
"navigation",
"run",
"publication",
]);
if (Object.keys(payload).some((key) => !allowed.has(key)))
throw new Error("Unknown public chat payload field");
const fields = (value, names) => {
if (
!value ||
typeof value !== "object" ||
Array.isArray(value) ||
Object.keys(value).some((key) => !names.split(" ").includes(key))
)
throw new Error("Unknown public chat projection field");
};
fields(payload.publication, "schema notice");
fields(payload.navigation, "suiteHref previous next");
for (const link of [payload.navigation.previous, payload.navigation.next])
if (link !== null) fields(link, "label href");
fields(
payload.run,
"model provider driver providerVersion runnerProvider acpxAgent acpxProfile requestedModel effectiveModelHistory configuration sessionId providerSessionId agentVersion managedProfile retainedSession retainedSessionStatus fixtureDigest runnerPackageDigest runnerdDigest startedAt finishedAt durationMs runnerBuild initialRevision finalRevision usage",
);
if (View on GitHub (pinned to 01ad858492)
Solutions
- Remove the unexpected top-level field from the payload before validation.
- If the generator intentionally added a new public field, add its name to the allowed Set in validatePublicChatPayload().
- Confirm the generator version matches the validator; regenerate the payload with the current generator.
- Check that payload post-processing (spreading extra objects into the payload) is not merging internal metadata into the public payload.
Example fix
// before
const payload = { ...publicProjection, runLog: raw.runLog };
// after
const payload = { ...publicProjection }; // no extra top-level fields Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = new Set(["attemptId","caseId","disposition","passed","checks","view","devtools","navigation","run","publication"]);
const extras = Object.keys(payload).filter((k) => !ALLOWED.has(k));
if (extras.length) console.warn("Remove extra top-level fields:", extras); Type guard
const hasOnlyAllowedKeys = (p, allowed) => p != null && Object.keys(p).every((k) => allowed.has(k));
Try / catch
try {
validatePublicChatPayload(payload);
} catch (err) {
if (err.message === "Unknown public chat payload field") {
console.error("Top-level allowlist mismatch; regenerate payload or update the allowlist", Object.keys(payload));
}
throw err;
} Prevention
- When adding a payload field, update the generator, the allowlist, and tests in one commit
- Avoid spreading whole internal payload objects into the public payload
- Keep a single shared constant for the top-level key set used by both producer and validator
- Snapshot-test the public payload shape to catch new keys immediately
When it happens
Trigger: Calling validatePublicChatPayload with a payload containing any top-level key outside the allowlist, e.g. an internal "runLog", "environment", or debug field added by the generator, or a deprecated field not yet removed after a schema change.
Common situations: A developer adds a new field to the run payload generator and forgets to allowlist it here; an older generator emits a field that was removed from the allowlist; serialization layers attach metadata (e.g. "meta", "version") to the payload object.
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
- Unknown public chat projection field
- Worktree seed manifest is missing source path diagnostics.
- unsupported request schema
- Public attempt must contain the read-only public chat projec
- Refusing non-allowlisted public protocol eval path ${file}
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b2e4b4ebbe8d5330.
Report an issue: GitHub.