{"record":{"id":"69e49f4177347fd1","repo":"paperclipai/paperclip","slug":"no-live-rosters-were-selected","errorCode":null,"errorMessage":"No live rosters were selected","messagePattern":"No live rosters were selected","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs","lineNumber":186,"sourceCode":"      rosterFile,\n      configFile: relative(programRoot, configPath).split(sep).join(\"/\"),\n      model: String(roster.model ?? config.model ?? \"unknown\"),\n      provider: String(config.provider ?? \"codex\"),\n      driver: String(config.driver ?? \"codex_app_server\"),\n      credentialName,\n      cases,\n    });\n  }\n  if (selected) {\n    const found = new Set(\n      rosters.flatMap((roster) => [roster.rosterId, roster.rosterFile]),\n    );\n    const missing = [...selected].filter((entry) => !found.has(entry));\n    if (missing.length > 0) {\n      throw new Error(`Unknown live roster selection: ${missing.join(\", \")}`);\n    }\n  }\n  if (rosters.length === 0) throw new Error(\"No live rosters were selected\");\n\n  const cells = rosters.flatMap((roster) =>\n    roster.cases.map((caseId) => ({\n      cellId: safeId(`${roster.rosterId}--${caseId}`, \"cell ID\"),\n      rosterId: roster.rosterId,\n      rosterFile: roster.rosterFile,\n      caseId,\n      model: roster.model,\n      provider: roster.provider,\n      driver: roster.driver,\n      credentialName: roster.credentialName,\n    })),\n  );\n  const shards = [[], []];\n  cells.forEach((cell, index) => shards[index % shards.length].push(cell));\n  if (shards.some((shard) => shard.length > 256)) {\n    throw new Error(\n      \"Protocol eval catalog exceeds the two-shard GitHub matrix limit\",","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs#L168-L204","documentation":"After optional selection filtering, buildProtocolEvalCatalog asserts that at least one roster survived. If the rosters array is empty (no roster files found, or a selection filtered everything out), there is nothing to build a campaign from, so it throws.","triggerScenarios":"Running the campaign script against a program root whose rosters directory contains no valid live-roster/v1 files, or supplying a 'selected' filter whose entries match no rosters (leaving zero after filtering).","commonSituations":"Running the script from the wrong working directory so no roster files are discovered; a selection string that skips the only available roster; an empty/renamed rosters directory in CI.","solutions":["Run from the correct program root where the rosters directory exists and is populated.","Remove or correct the roster selection so at least one roster is included.","Add roster files if the directory is genuinely empty."],"exampleFix":"// before\nnode runner-protocol-eval-campaign.mjs --roster nonexistent-roster\n// after\nnode runner-protocol-eval-campaign.mjs  # or select an existing roster id","handlingStrategy":"validation","validationCode":"if (rosters.length === 0) {\n  console.error(\"No live rosters found; check program root and rosters directory\");\n  process.exit(1);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const catalog = await buildProtocolEvalCatalog(args);\n} catch (err) {\n  if (err.message === \"No live rosters were selected\") {\n    console.error(\"Check cwd and roster selection flags\");\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Run the script from the repo/program root where rosters are discovered automatically.","Confirm the rosters directory is non-empty before invoking the script in CI."],"tags":["cli","empty-selection","config"],"backgroundTag":"empty-result-set","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"}