paperclipai/paperclip · error · Error

Invalid published campaign ID

Error message

Invalid published campaign ID

What it means

writeProtocolEvalPublicationLinks publishes protocol eval history links and refuses to process campaign IDs that don't match SAFE_CAMPAIGN. The error means the campaignId extracted from the publish result was missing or contained characters outside the allowlisted format, so the script aborts before writing GitHub Actions outputs to avoid injecting unsafe values into the public site URL paths.

Source

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

  await writeFile(index, renderProtocolEvalHistoryIndex(history, stylesheetHref));
  await uploadFile(
    validatedDestination.bucket,
    `${validatedDestination.prefix}/index.html`,
    index,
    "no-cache",
  );
  return {
    campaignId: campaign.campaignId,
    bundleDigest: manifest.bundleDigest,
    historySize: history.campaigns.length,
    reportUrl: `${validatedDestination.publicBaseUrl}/${campaignPrefix}/index.html`,
    historyUrl: `${validatedDestination.publicBaseUrl}/${validatedDestination.prefix}/index.html`,
  };
}

export async function writeProtocolEvalPublicationLinks(result, environment = process.env) {
  const { campaignId, reportUrl, historyUrl } = result;
  if (!SAFE_CAMPAIGN.test(campaignId)) throw new Error("Invalid published campaign ID");
  const safeUrl = (value) => {
    const url = new URL(value);
    if (url.protocol !== "https:" || url.username || url.password || /[\r\n<>]/.test(value))
      throw new Error("Invalid published report URL");
    return url.href;
  };
  const report = safeUrl(reportUrl);
  const history = safeUrl(historyUrl);
  if (environment.GITHUB_OUTPUT)
    await appendFile(environment.GITHUB_OUTPUT, `report_url=${report}\nhistory_url=${history}\n`);
  if (environment.GITHUB_STEP_SUMMARY)
    await appendFile(environment.GITHUB_STEP_SUMMARY, `## Published Runner Evalbook\n\n[Open this run's Evalbook](<${report}>) · [All eval runs](<${history}>)\n\nCampaign: \`${campaignId}\`\n\nPublic replay uses the Runner Lab theme; full evidence is in the workflow artifact.\n`);
}

async function main() {
  const result = await publishProtocolEvalHistory({
    viewerRoot: process.env.PAPERCLIP_RUNNER_PROTOCOL_EVAL_VIEWER_DIR,
    reportRoot: resolve(

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect the campaignId value passed in result and correct it to match SAFE_CAMPAIGN (e.g. lowercase alphanumerics/hyphens only)
  2. Regenerate the campaign so campaign.json gets a properly formatted campaignId
  3. Add a console log of result.campaignId before the throw to diagnose the actual value
  4. Pass the campaign ID explicitly from the workflow step rather than deriving it from an untrusted source

Example fix

// before
await writeProtocolEvalPublicationLinks({ campaignId: process.env.GITHUB_RUN_ID, ... });
// after
await writeProtocolEvalPublicationLinks({ campaignId: 'gha-12345-1', ... });
Defensive patterns

Strategy: validation

Validate before calling

if (!/^[A-Za-z0-9_-]+$/.test(campaignId)) throw new Error('campaignId fails SAFE_CAMPAIGN: ' + campaignId);

Type guard

const hasSafeCampaignId = (r) => typeof r?.campaignId === 'string' && r.campaignId.length > 0;

Try / catch

try { await writeProtocolEvalPublicationLinks(result); } catch (e) { if (e.message === 'Invalid published campaign ID') { console.error('Bad campaignId:', result.campaignId); } throw e; }

Prevention

When it happens

Trigger: Calling writeProtocolEvalPublicationLinks with a result whose campaignId is undefined, empty, or fails the SAFE_CAMPAIGN regex (e.g. contains slashes, uppercase, spaces, or is a full URL instead of a bare ID).

Common situations: A CI workflow passes a run identifier or branch name instead of the campaign ID; the upstream campaign.json has a malformed or legacy campaignId; the result object was built incorrectly and the field is undefined.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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