paperclipai/paperclip · error · Error
Unsupported live campaign schema in ${campaignPath}
Error message
Unsupported live campaign schema in ${campaignPath} What it means
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.
Source
Thrown at packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs:93
if (!value?.trim() || value.trim() === "all") return null;
const selected = value
.split(",")
.map((entry) => entry.trim())
.filter(Boolean);
if (selected.length === 0 || new Set(selected).size !== selected.length) {
throw new Error("Roster selection must contain unique comma-separated IDs");
}
return new Set(selected);
}
async function maintainedRosterSelection(programRoot) {
const campaignPath = resolve(programRoot, "campaigns/live-direct-full.json");
const campaign = await loadObject(campaignPath);
if (
campaign.schema !== "paperclip-runner/live-campaign/v1" ||
!Array.isArray(campaign.lanes)
) {
throw new Error(`Unsupported live campaign schema in ${campaignPath}`);
}
const selected = campaign.lanes
.filter((lane) => lane.executionClass !== "disabled")
.map((lane) => {
const rosterPath = inside(
programRoot,
resolve(dirname(campaignPath), String(lane.roster ?? "")),
"Campaign roster",
);
return basename(rosterPath);
});
if (selected.length === 0 || new Set(selected).size !== selected.length) {
throw new Error(
"Maintained live campaign must contain unique enabled rosters",
);
}
return new Set(selected);
}View on GitHub (pinned to 01ad858492)
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.
Example fix
// before
{ "schema": "live-campaign", "laneList": [...] }
// after
{ "schema": "paperclip-runner/live-campaign/v1", "lanes": [...] } Defensive patterns
Strategy: validation
Validate before calling
const campaign = JSON.parse(await readFile(campaignPath, "utf8"));
if (campaign.schema !== "paperclip-runner/live-campaign/v1" || !Array.isArray(campaign.lanes)) throw new Error(`Unsupported campaign schema in ${campaignPath}`); Type guard
const isLiveCampaignV1 = (c) => c?.schema === "paperclip-runner/live-campaign/v1" && Array.isArray(c.lanes);
Try / catch
try {
const selection = await maintainedRosterSelection(programRoot);
} catch (err) {
if (err.message.startsWith("Unsupported live campaign schema")) console.error("Check campaigns/live-direct-full.json schema field and lanes array.");
throw err;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Worktree seed manifest is missing source path diagnostics.
- unsupported request schema
- Public attempt must contain the read-only public chat projec
- Unknown public chat payload field
- Unknown public chat projection field
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/1a9016cef1f66417.
Report an issue: GitHub.