{"record":{"id":"b594db491d853210","repo":"paperclipai/paperclip","slug":"evaluation-issue-mismatch","errorCode":"evaluation_issue_mismatch","errorMessage":"Watchdog decision evaluation issue is not bound to the target run","messagePattern":"Watchdog decision evaluation issue is not bound to the target run","errorType":"error_code","errorClass":"WatchdogDecisionApplicationError","httpStatus":null,"severity":"error","filePath":"server/src/modules/active-run-watchdog/application/use-cases.ts","lineNumber":173,"sourceCode":"      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\",\n        \"Only the board or the assigned recovery owner can record watchdog decisions\",\n      );\n    }\n\n    if (evaluationIssue && (\n      evaluationIssue.originKind !== STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND ||\n      evaluationIssue.originId !== run.id\n    )) {\n      throw new WatchdogDecisionApplicationError(\n        \"evaluation_issue_mismatch\",\n        \"Watchdog decision evaluation issue is not bound to the target run\",\n      );\n    }\n\n    const createdByRunId = input.actor.type === \"agent\"\n      ? input.actor.runId ?? input.createdByRunId ?? null\n      : input.actor.type === \"board\"\n        ? input.actor.runId ?? input.createdByRunId ?? null\n        : null;\n    if (createdByRunId) {\n      const creatorRun = await deps.reader.findRunForCompany(input.companyId, createdByRunId);\n      const sameAgent = input.actor.type !== \"agent\" || creatorRun?.agentId === input.actor.agentId;\n      if (!creatorRun || !sameAgent) {\n        throw new WatchdogDecisionApplicationError(\n          \"creator_run_invalid\",\n          \"createdByRunId is not valid for this watchdog decision actor\",\n        );","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/modules/active-run-watchdog/application/use-cases.ts#L155-L191","documentation":"When a decision references an evaluation issue, that issue must be a stale-active-run evaluation bound to the exact heartbeat run targeted by the decision (originKind === STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND and originId === run.id). Otherwise the use case throws code evaluation_issue_mismatch, preventing decisions on one run from being laundered through another run's evaluation issue.","triggerScenarios":"recordWatchdogDecision called with an evaluationIssueId whose originId points to a different heartbeat run than input.runId, or whose originKind is not the stale-active-run evaluation kind (e.g. a generic issue or a different origin type).","commonSituations":"UI or scripts reusing an old evaluation issue ID with a new run ID after a run was retried/recreated; mixing up run IDs across companies or heartbeat cycles; passing a non-watchdog issue ID that happens to exist in the company.","solutions":["Re-read the evaluation issue and confirm originId matches the runId you are recording against","Refetch the correct stale-active-run evaluation issue for the current run (it is recreated per run) instead of caching across runs","If the run was replaced, locate the new run's evaluation issue before recording","Verify originKind is STALE_ACTIVE_RUN_EVALUATION_ORIGIN_KIND, not another issue origin"],"exampleFix":"// before\nawait recordWatchdogDecision({ runId: newRunId, evaluationIssueId: oldRunIssueId, ... });\n// after\nconst issue = await findStaleActiveRunEvaluation(companyId, newRunId); // originId === newRunId\nawait recordWatchdogDecision({ runId: newRunId, evaluationIssueId: issue.id, ... });","handlingStrategy":"validation","validationCode":"if (issue && (issue.originKind !== 'stale_active_run' || issue.originId !== runId)) throw new Error('evaluation issue is not bound to target run');","typeGuard":"function isBoundToRun(issue: { originKind: string; originId: string }, runId: string, originKind: string) { return issue.originKind === originKind && issue.originId === runId; }","tryCatchPattern":"try { await recordWatchdogDecision(input); } catch (e) { if (e.code === 'evaluation_issue_mismatch') { /* refetch the evaluation issue for the current runId */ } else throw e; }","preventionTips":["Look up the evaluation issue by (companyId, runId) origin binding rather than caching IDs across runs","Invalidate cached issue IDs whenever a run is retried or recreated","Assert originKind/originId in client code before submitting the decision"],"tags":["validation","watchdog","state-mismatch","issues"],"backgroundTag":"invalid-state-transition","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"}