{"record":{"id":"1a9016cef1f66417","repo":"paperclipai/paperclip","slug":"unsupported-live-campaign-schema-in-campaignpath","errorCode":null,"errorMessage":"Unsupported live campaign schema in ${campaignPath}","messagePattern":"Unsupported live campaign schema in (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs","lineNumber":93,"sourceCode":"  if (!value?.trim() || value.trim() === \"all\") return null;\n  const selected = value\n    .split(\",\")\n    .map((entry) => entry.trim())\n    .filter(Boolean);\n  if (selected.length === 0 || new Set(selected).size !== selected.length) {\n    throw new Error(\"Roster selection must contain unique comma-separated IDs\");\n  }\n  return new Set(selected);\n}\n\nasync function maintainedRosterSelection(programRoot) {\n  const campaignPath = resolve(programRoot, \"campaigns/live-direct-full.json\");\n  const campaign = await loadObject(campaignPath);\n  if (\n    campaign.schema !== \"paperclip-runner/live-campaign/v1\" ||\n    !Array.isArray(campaign.lanes)\n  ) {\n    throw new Error(`Unsupported live campaign schema in ${campaignPath}`);\n  }\n  const selected = campaign.lanes\n    .filter((lane) => lane.executionClass !== \"disabled\")\n    .map((lane) => {\n      const rosterPath = inside(\n        programRoot,\n        resolve(dirname(campaignPath), String(lane.roster ?? \"\")),\n        \"Campaign roster\",\n      );\n      return basename(rosterPath);\n    });\n  if (selected.length === 0 || new Set(selected).size !== selected.length) {\n    throw new Error(\n      \"Maintained live campaign must contain unique enabled rosters\",\n    );\n  }\n  return new Set(selected);\n}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs#L75-L111","documentation":"maintainedRosterSelection loads campaigns/live-direct-full.json from the program root and requires it to declare schema \"paperclip-runner/live-campaign/v1\" and an array 'lanes'. Any other shape is rejected with the campaign path in the message. This keeps the maintained campaign contract explicit so downstream lane filtering behaves predictably.","triggerScenarios":"Calling maintainedRosterSelection when the campaign file's schema field is missing, set to another version string, or when campaign.lanes is not an array (absent, an object, or null).","commonSituations":"Campaign file edited to a newer/renamed schema string without updating the script; lanes field renamed or restructured; stale campaign file from an older layout; file replaced with a differently-shaped export.","solutions":["Set \"schema\": \"paperclip-runner/live-campaign/v1\" at the top level of campaigns/live-direct-full.json.","Ensure the campaign defines lanes as an array of lane objects.","If the schema intentionally changed, update maintainedRosterSelection (and related loaders) to accept the new schema version."],"exampleFix":"// before\n{ \"schema\": \"live-campaign\", \"laneList\": [...] }\n// after\n{ \"schema\": \"paperclip-runner/live-campaign/v1\", \"lanes\": [...] }","handlingStrategy":"validation","validationCode":"const campaign = JSON.parse(await readFile(campaignPath, \"utf8\"));\nif (campaign.schema !== \"paperclip-runner/live-campaign/v1\" || !Array.isArray(campaign.lanes)) throw new Error(`Unsupported campaign schema in ${campaignPath}`);","typeGuard":"const isLiveCampaignV1 = (c) => c?.schema === \"paperclip-runner/live-campaign/v1\" && Array.isArray(c.lanes);","tryCatchPattern":"try {\n  const selection = await maintainedRosterSelection(programRoot);\n} catch (err) {\n  if (err.message.startsWith(\"Unsupported live campaign schema\")) console.error(\"Check campaigns/live-direct-full.json schema field and lanes array.\");\n  throw err;\n}","preventionTips":["Pin the schema string in a shared constant and import it in both writer and reader.","Validate campaign files in CI against the live-campaign/v1 shape.","When bumping schema versions, migrate existing campaign files in the same change."],"tags":["schema","campaign","validation"],"backgroundTag":"unsupported-schema-version","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}