{"record":{"id":"9086e4f3ab6a09bc","repo":"paperclipai/paperclip","slug":"schedule-references-unknown-candidate-entry-cand","errorCode":null,"errorMessage":"schedule references unknown candidate ${entry.candidateId}","messagePattern":"schedule references unknown candidate (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/eval/live-workflow-matrix.ts","lineNumber":488,"sourceCode":"export async function executeRunnerLiveSchedule(\n  schedule: RunnerLiveEvalSchedule,\n  execute: (\n    entry: RunnerLiveScheduleEntry,\n    candidate: RunnerLiveEvalCandidate,\n  ) => Promise<RunnerWorkflowObservation>,\n  onInfrastructureFailure?: (\n    entry: RunnerLiveScheduleEntry,\n    candidate: RunnerLiveEvalCandidate,\n    error: RunnerWorkflowInfrastructureError,\n  ) => RunnerWorkflowObservation | Promise<RunnerWorkflowObservation>,\n): Promise<RunnerWorkflowObservation[]> {\n  const results: RunnerWorkflowObservation[] = [];\n  for (const entry of schedule.entries) {\n    const resolved = schedule.candidates.find(\n      (candidate) => candidate.id === entry.candidateId,\n    );\n    if (!resolved)\n      throw new Error(\n        `schedule references unknown candidate ${entry.candidateId}`,\n      );\n    let infrastructureAttempts = 0;\n    while (true) {\n      try {\n        results.push(await execute(entry, resolved));\n        break;\n      } catch (error) {\n        if (!(error instanceof RunnerWorkflowInfrastructureError)) {\n          throw error;\n        }\n        if (!error.retryable || infrastructureAttempts >= 1) {\n          if (onInfrastructureFailure === undefined) throw error;\n          results.push(await onInfrastructureFailure(entry, resolved, error));\n          break;\n        }\n        infrastructureAttempts += 1;\n      }","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/eval/live-workflow-matrix.ts#L470-L506","documentation":"Thrown by executeRunnerLiveSchedule when a schedule entry's candidateId does not match any candidate in schedule.candidates. The function builds the candidate lookup inside the execution loop and fails fast rather than silently skipping malformed schedule entries. It indicates the schedule was constructed with inconsistent entry/candidate data.","triggerScenarios":"Calling executeRunnerLiveSchedule with a LiveWorkflowSchedule where some entry.candidateId was never added to schedule.candidates (typo, filtered-out candidate, or hand-built schedule).","commonSituations":"Hand-assembled schedules in eval scripts; candidates deduplicated or filtered after entries were generated; candidate IDs regenerated (e.g. UUIDs) after entries referenced old IDs.","solutions":["Inspect schedule.entries and schedule.candidates; make every entry.candidateId exist in candidates before calling executeRunnerLiveSchedule","Fix the schedule builder so entries are generated from the same candidate list it embeds (derive entry.candidateId from candidates[i].id)","If filtering candidates, filter entries with the same predicate","Add a pre-call validation that every entry.candidateId is in the candidate id set"],"exampleFix":"// before\nconst schedule = { candidates: candidates.filter(c => c.enabled), entries: allEntries };\nawait executeRunnerLiveSchedule(schedule);\n// after\nconst enabled = candidates.filter(c => c.enabled);\nconst schedule = { candidates: enabled, entries: allEntries.filter(e => enabled.some(c => c.id === e.candidateId)) };\nawait executeRunnerLiveSchedule(schedule);","handlingStrategy":"validation","validationCode":"const ids = new Set(schedule.candidates.map(c => c.id));\nconst bad = schedule.entries.filter(e => !ids.has(e.candidateId));\nif (bad.length) throw new Error(`entries reference unknown candidates: ${bad.map(e => e.candidateId).join(', ')}`);","typeGuard":"function isScheduleValid(schedule: { candidates: {id: string}[]; entries: {candidateId: string}[] }): boolean {\n  const ids = new Set(schedule.candidates.map(c => c.id));\n  return schedule.entries.every(e => ids.has(e.candidateId));\n}","tryCatchPattern":"try {\n  await executeRunnerLiveSchedule(schedule);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('schedule references unknown candidate')) {\n    // log the schedule and skip/rebuild\n  } else throw err;\n}","preventionTips":["Build entries and candidates from a single source of truth","Validate schedule integrity before passing it to the runner","Filter candidates and entries with the same predicate"],"tags":["eval","schedule","data-consistency"],"backgroundTag":"schedule-candidate-not-found","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-02T18:44:00.616Z","contentChangedAt":"2026-09-02T18:44:00.616Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}