{"record":{"id":"236c077ce0ffcaef","repo":"mastra-ai/mastra","slug":"durable-agent-recover-agent-mismatch","errorCode":"DURABLE_AGENT_RECOVER_AGENT_MISMATCH","errorMessage":"DurableAgent \"${this.name}\" recover(${runId}): persisted run belongs to agent \"${workflowInput.agentId}\", not \"${this.id}\".","messagePattern":"DurableAgent \"(.+?)\" recover\\((.+?)\\): persisted run belongs to agent \"(.+?)\", not \"(.+?)\"\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/durable/durable-agent.ts","lineNumber":733,"sourceCode":"    }\n\n    const snapshot =\n      typeof persisted.snapshot === 'string'\n        ? (JSON.parse(persisted.snapshot) as WorkflowRunState)\n        : persisted.snapshot;\n    const workflowInput = snapshot?.context?.input as DurableAgenticWorkflowInput | undefined;\n    if (!workflowInput || workflowInput.__workflowKind !== 'durable-agent') {\n      throw new MastraError({\n        id: 'DURABLE_AGENT_RECOVER_INVALID_SNAPSHOT',\n        domain: ErrorDomain.AGENT,\n        category: ErrorCategory.SYSTEM,\n        text: `DurableAgent \"${this.name}\" recover(${runId}): persisted snapshot does not contain a durable-agent workflow input.`,\n        details: { agentName: this.name, runId },\n      });\n    }\n\n    if (workflowInput.agentId !== this.id) {\n      throw new MastraError({\n        id: 'DURABLE_AGENT_RECOVER_AGENT_MISMATCH',\n        domain: ErrorDomain.AGENT,\n        category: ErrorCategory.USER,\n        text: `DurableAgent \"${this.name}\" recover(${runId}): persisted run belongs to agent \"${workflowInput.agentId}\", not \"${this.id}\".`,\n        details: { agentName: this.name, runId, ownerAgentId: workflowInput.agentId },\n      });\n    }\n\n    return workflowInput;\n  }\n\n  /**\n   * Rebuild and register the stream for a claimed recovery attempt. Rolls back\n   * every partial registration and releases the claim if setup fails.\n   */\n  async #setupRecoveredStream({\n    runId,\n    workflowInput,","sourceCodeStart":715,"sourceCodeEnd":751,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/durable/durable-agent.ts#L715-L751","documentation":"Once the snapshot's durable-agent workflow input is validated, #loadRecoverableWorkflowInput compares workflowInput.agentId with this.id. If the persisted run was created by a different agent, recover() refuses to hijack another agent's run and throws this USER error with the owning agent's ID in details.ownerAgentId.","triggerScenarios":"Calling recover(runId) on agent A when the runId was produced by agent B — e.g. shared storage across agents, wrong agent instance retrieved from mastra.getAgent(), or agent renamed/re-created with a new id so old runs no longer match this.id.","commonSituations":"Multiple agents sharing one storage backend and a scheduler recovering failed runs against the wrong agent; renaming an agent (id changes) and then trying to recover its old runs; copy-pasted recovery job not parameterized per agent.","solutions":["Call recover() on the owning agent — the error's details.ownerAgentId tells you which one.","Fix agent resolution (e.g. mastra.getAgent(ownerAgentId)) in the recovery job.","If the agent's id changed intentionally, migrate or re-attribute old runs, or re-run the tasks under the new agent.","Filter recovery queues by agentId so each agent only recovers its own runs."],"exampleFix":"// before\nawait agentA.recover(runId); // run belongs to agentB\n// after\nconst run = await workflowsStore.getWorkflowRunById({ runId, workflowName: DurableStepIds.AGENTIC_LOOP });\nconst input = JSON.parse(String(run.snapshot)).context.input;\nconst owner = mastra.getAgent(input.agentId);\nawait owner.recover(runId);","handlingStrategy":"validation","validationCode":"const input = getWorkflowInput(runId); // parse snapshot.context.input\nif (input?.agentId !== agent.id) {\n  throw new Error(`Run ${runId} belongs to agent ${input?.agentId}; use that agent to recover.`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await agent.recover(runId);\n} catch (e) {\n  if (String(e?.id) === 'DURABLE_AGENT_RECOVER_AGENT_MISMATCH') {\n    const owner = mastra.getAgent(e?.details?.ownerAgentId);\n    await owner.recover(runId); // route to owning agent\n  } else throw e;\n}","preventionTips":["Tag recovery queue entries with the owning agentId and route them to that agent.","Don't rename agent ids if existing runs must remain recoverable, or migrate run records accordingly.","In shared-storage setups, always resolve the agent from the run's stored agentId before recovering."],"tags":["durable-agent","recovery","ownership","agent-mismatch","user-input"],"backgroundTag":"run-owner-agent-mismatch","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}