{"record":{"id":"5c4f33e199597b10","repo":"paperclipai/paperclip","slug":"evaluation-issue-required","errorCode":"evaluation_issue_required","errorMessage":"Agent watchdog decisions require the target evaluation issue","messagePattern":"Agent watchdog decisions require the target evaluation issue","errorType":"error_code","errorClass":"WatchdogDecisionApplicationError","httpStatus":null,"severity":"error","filePath":"server/src/modules/active-run-watchdog/application/use-cases.ts","lineNumber":146,"sourceCode":"  createdByRunId?: string | null;\n  now?: Date;\n};\n\nexport function createRecordWatchdogDecision(deps: RecordWatchdogDecisionDeps) {\n  return async function recordWatchdogDecision(\n    input: RecordWatchdogDecisionUseCaseInput,\n  ): Promise<WatchdogDecisionRecord> {\n    const run = await deps.reader.findRunForCompany(input.companyId, input.runId);\n    if (!run) throw new WatchdogDecisionApplicationError(\"run_not_found\", \"Heartbeat run not found\");\n\n    const evaluationIssue = input.evaluationIssueId\n      ? await deps.reader.findEvaluationIssueById(input.companyId, input.evaluationIssueId)\n      : null;\n    if (input.evaluationIssueId && !evaluationIssue) {\n      throw new WatchdogDecisionApplicationError(\"evaluation_issue_not_found\", \"Evaluation issue not found\");\n    }\n    if (input.actor.type === \"agent\" && !evaluationIssue) {\n      throw new WatchdogDecisionApplicationError(\n        \"evaluation_issue_required\",\n        \"Agent watchdog decisions require the target evaluation issue\",\n      );\n    }\n\n    const boardActor = input.actor.type === \"board\";\n    const assignedRecoveryOwner =\n      input.actor.type === \"agent\" &&\n      Boolean(input.actor.agentId) &&\n      evaluationIssue !== null &&\n      evaluationIssue.originKind === STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND &&\n      evaluationIssue.originId === run.id &&\n      evaluationIssue.hiddenAt === null &&\n      ![\"done\", \"cancelled\"].includes(evaluationIssue.status) &&\n      evaluationIssue.assigneeAgentId === input.actor.agentId;\n    if (!boardActor && !assignedRecoveryOwner) {\n      throw new WatchdogDecisionApplicationError(\n        \"not_authorized\",","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/modules/active-run-watchdog/application/use-cases.ts#L128-L164","documentation":"Agents are only permitted to record watchdog decisions when a target evaluation issue is present in the input; if input.actor.type === 'agent' and no evaluation issue resolved, the use case throws code evaluation_issue_required. The board may record decisions without an evaluation issue, but agents cannot — the issue is their authorization anchor (they must be its assignee).","triggerScenarios":"An agent-key authenticated request calls recordWatchdogDecision without evaluationIssueId, or with one that resolved to null (which then hits this check after the not-found check), so the agent has no evaluation issue to bind its decision to.","commonSituations":"Agent scripts recording recovery decisions without including the evaluation issue from the stale-active-run notification; agents operating after their evaluation issue was closed (done/cancelled) or hidden so the lookup returns null; misconfigured automation calling with board-style payloads.","solutions":["Always include a valid evaluationIssueId when calling as an agent, sourced from the stale-active-run evaluation issue assigned to the agent","Confirm the agent is the assignee of a visible, open (not done/cancelled) stale-active-run evaluation issue for the run","If no evaluation issue exists, have a board actor record the decision instead","Check that the issue's hiddenAt is null and status is not done/cancelled, which would cause the resolved issue to be rejected downstream"],"exampleFix":"// before (agent call without issue)\nawait recordWatchdogDecision({ actor: { type: 'agent', agentId }, companyId, runId });\n// after\nawait recordWatchdogDecision({ actor: { type: 'agent', agentId }, companyId, runId, evaluationIssueId: assignedIssueId });","handlingStrategy":"validation","validationCode":"if (actor.type === 'agent' && !evaluationIssueId) throw new Error('agent watchdog decisions require evaluationIssueId');","typeGuard":"function agentInputRequiresIssue(input: { actor: { type: string }; evaluationIssueId?: string }) { return !(input.actor.type === 'agent' && !input.evaluationIssueId); }","tryCatchPattern":"null","preventionTips":["Agent tooling should treat evaluationIssueId as a required field when actor.type === 'agent'","Verify the agent still owns a live (unhidden, not done/cancelled) evaluation issue before acting","Route decisions without an evaluation issue through a board actor instead"],"tags":["authorization","watchdog","agent","missing-required-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}