paperclipai/paperclip · error · Error

Public report campaign metadata is invalid

Error message

Public report campaign metadata is invalid

What it means

validatePublicProtocolEvalReport requires campaign.json to declare schema "paperclip.runner-protocol-eval.campaign/v1" and a campaignId matching SAFE_CAMPAIGN (gha-<run>-<attempt> optionally suffixed with -report-<slug>). If either check fails the report metadata cannot be trusted for immutable public publication, so the publisher refuses it. This protects the S3 history from arbitrary or forged campaign identifiers.

Source

Thrown at packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs:237

        );
      }
    }
  }
  if (viewer) {
    for (const file of viewer.files.keys())
      if (!files.includes(file))
        throw new Error(`Missing public viewer asset: ${file}`);
    if (files.some((file) => /^attempts\/[^/]+\.html$/.test(file)))
      throw new Error(
        "Chat Evalbook must not mix in legacy plain attempt pages",
      );
  }
  const campaign = await loadObject(join(root, "campaign.json"));
  if (
    campaign.schema !== "paperclip.runner-protocol-eval.campaign/v1" ||
    !SAFE_CAMPAIGN.test(String(campaign.campaignId ?? ""))
  ) {
    throw new Error("Public report campaign metadata is invalid");
  }
  return { files, campaign };
}

export async function createProtocolEvalBundleManifest(
  reportRoot,
  campaignId,
  { viewerRoot } = {},
) {
  if (!SAFE_CAMPAIGN.test(campaignId))
    throw new Error("Unsafe protocol eval campaign ID");
  const { files, campaign } = await validatePublicProtocolEvalReport(
    reportRoot,
    { viewerRoot },
  );
  if (campaign.campaignId !== campaignId)
    throw new Error("Report campaign ID does not match publication target");
  const entries = await Promise.all(

View on GitHub (pinned to 01ad858492)

Solutions

  1. Open <reportRoot>/campaign.json and confirm schema === "paperclip.runner-protocol-eval.campaign/v1"
  2. Set campaignId to the GHA form gha-<run_number>-<attempt> (optionally -report-<slug>, slug lowercase alnum/hyphen, max 40 chars)
  3. Regenerate the report with the current eval pipeline so it writes valid campaign metadata
  4. If testing locally, use a compliant synthetic ID like gha-1-1-test

Example fix

// before (campaign.json)
{ "schema": "campaign/v2", "campaignId": "local_run_42" }
// after
{ "schema": "paperclip.runner-protocol-eval.campaign/v1", "campaignId": "gha-42-1" }
Defensive patterns

Strategy: validation

Validate before calling

const campaign = JSON.parse(fs.readFileSync(path.join(reportRoot, "campaign.json"), "utf8"));
const SAFE = /^gha-[1-9][0-9]*-[1-9][0-9]*(-report-[a-z0-9][a-z0-9-]{0,39})?$/;
if (campaign.schema !== "paperclip.runner-protocol-eval.campaign/v1" || !SAFE.test(String(campaign.campaignId)))
  throw new Error("invalid campaign.json before publish");

Type guard

const isValidCampaign = (c) =>
  !!c && typeof c === "object" && !Array.isArray(c) &&
  c.schema === "paperclip.runner-protocol-eval.campaign/v1" &&
  /^gha-[1-9][0-9]*-[1-9][0-9]*(-report-[a-z0-9][a-z0-9-]{0,39})?$/.test(String(c.campaignId ?? ""));

Try / catch

try {
  await publishProtocolEvalHistory({ reportRoot, destination, viewerRoot });
} catch (e) {
  if (String(e.message).includes("campaign metadata is invalid")) {
    console.error("check campaign.json schema/campaignId:", fs.readFileSync(path.join(reportRoot, "campaign.json"), "utf8"));
  }
  throw e;
}

Prevention

When it happens

Trigger: campaign.json missing the schema field or carrying a wrong/older schema value; campaignId absent, empty, or not matching the gha-N-N(-report-slug) pattern (e.g. a local name like 'my-eval-run' or containing uppercase/underscores); campaign.json being a JSON array or scalar (loadObject throws a different error, but a malformed object shape lands here).

Common situations: Running the publish script on a report directory produced by an outdated generator; hand-crafting a campaign.json for testing; CI environment producing a campaign ID that does not follow the GHA run/attempt convention.

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


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