paperclipai/paperclip · error · Error
Live roster repeats a case
Error message
Live roster ${rosterId} repeats a case What it means
buildProtocolEvalCatalog maps each roster.cases entry through safeId and then checks whether the resulting list contains duplicates by comparing Set size to array length. Case IDs must be unique within a roster because each becomes a distinct eval cell keyed by '<rosterId>--<caseId>'; a duplicate would silently overwrite or double-run a cell.
Solutions
- Open the roster file and delete the duplicated case ID from 'cases'.
- Deduplicate programmatically before running: [...new Set(roster.cases)].
- If two distinct scenarios share a name, rename one case ID so each is unique.
Example fix
// before "cases": ["case-001", "case-002", "case-001"] // after "cases": ["case-001", "case-002"]
Defensive patterns
Strategy: validation
Validate before calling
const ids = roster.cases.map(String);
if (new Set(ids).size !== ids.length) {
throw new Error(`${rosterFile}: duplicate case IDs`);
} Type guard
function casesAreUnique(r) {
return Array.isArray(r.cases) && new Set(r.cases).size === r.cases.length;
} Prevention
- Generate case lists programmatically from a single source of truth instead of copy-pasting.
- Deduplicate with a Set when merging rosters from branches.
When it happens
Trigger: A live roster file's 'cases' array contains the same case ID string twice (e.g. ["case-001", "case-001"]).
Common situations: Merging roster files or case lists from two branches without deduplicating; copy-paste adding the same case twice; programmatic generation appending a case that is already listed.
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
- ACPX profile requires exact model ; received
- ACPX model must not be empty
- ACPX provider identity contains an invalid permission mode
- ACPX provider identity contains invalid lifetime fences
- AWS AgentCore evals require exact model…
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/37a01ddbc2376bf5.
Report an issue: GitHub.
Appendix: source
Thrown at packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs:164
if (selected && !selected.has(rosterId) && !selected.has(rosterFile)) {
continue;
}
if (roster.schema !== "paperclip-runner/live-roster/v1") {
throw new Error(`Unsupported live roster schema in ${rosterFile}`);
}
if (!Array.isArray(roster.cases) || roster.cases.length === 0) {
throw new Error(`Live roster ${rosterId} has no cases`);
}
const configPath = inside(
programRoot,
resolve(rosterRoot, String(roster.config ?? "")),
`Config for ${rosterId}`,
);
const config = await loadObject(configPath);
const credentialName = credentialForConfig(config);
const cases = roster.cases.map((caseId) => safeId(caseId, "case ID"));
if (new Set(cases).size !== cases.length) {
throw new Error(`Live roster ${rosterId} repeats a case`);
}
rosters.push({
rosterId,
rosterFile,
configFile: relative(programRoot, configPath).split(sep).join("/"),
model: String(roster.model ?? config.model ?? "unknown"),
provider: String(config.provider ?? "codex"),
driver: String(config.driver ?? "codex_app_server"),
credentialName,
cases,
});
}
if (selected) {
const found = new Set(
rosters.flatMap((roster) => [roster.rosterId, roster.rosterFile]),
);
const missing = [...selected].filter((entry) => !found.has(entry));
if (missing.length > 0) {View on GitHub (pinned to 01ad858492)