{"record":{"id":"24ebaaa69dc4faf2","repo":"mastra-ai/mastra","slug":"durable-agent-recover-lease-acquire-failed","errorCode":"DURABLE_AGENT_RECOVER_LEASE_ACQUIRE_FAILED","errorMessage":"DurableAgent \"${this.name}\" recover(${runId}): failed to acquire the recovery lease.","messagePattern":"DurableAgent \"(.+?)\" recover\\((.+?)\\): failed to acquire the recovery lease\\.","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/durable/durable-agent.ts","lineNumber":589,"sourceCode":"    const localOwner = localRecoveryClaims.get(key);\n    if (localOwner) {\n      throw new MastraError({\n        id: 'DURABLE_AGENT_RECOVER_ALREADY_IN_PROGRESS',\n        domain: ErrorDomain.AGENT,\n        category: ErrorCategory.USER,\n        text: `DurableAgent \"${this.name}\" recover(${runId}): another process is already recovering this run.`,\n        details: { agentName: this.name, runId },\n      });\n    }\n    localRecoveryClaims.set(key, owner);\n\n    const leaseAcquireStartedAt = Date.now();\n    let acquired: Awaited<ReturnType<LeaseProvider['acquireLease']>>;\n    try {\n      acquired = await provider.acquireLease(key, owner, RECOVERY_LEASE_TTL_MS);\n    } catch (cause) {\n      if (localRecoveryClaims.get(key) === owner) localRecoveryClaims.delete(key);\n      throw new MastraError(\n        {\n          id: 'DURABLE_AGENT_RECOVER_LEASE_ACQUIRE_FAILED',\n          domain: ErrorDomain.AGENT,\n          category: ErrorCategory.SYSTEM,\n          text: `DurableAgent \"${this.name}\" recover(${runId}): failed to acquire the recovery lease.`,\n          details: { agentName: this.name, runId },\n        },\n        cause,\n      );\n    }\n\n    if (!acquired.acquired) {\n      if (localRecoveryClaims.get(key) === owner) localRecoveryClaims.delete(key);\n      throw new MastraError({\n        id: 'DURABLE_AGENT_RECOVER_ALREADY_IN_PROGRESS',\n        domain: ErrorDomain.AGENT,\n        category: ErrorCategory.USER,\n        text: `DurableAgent \"${this.name}\" recover(${runId}): another process is already recovering this run.`,","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/durable/durable-agent.ts#L571-L607","documentation":"#acquireRecoveryLease asks the configured LeaseProvider to acquire a distributed lease for the recovery key. If provider.acquireLease() itself throws (backend unreachable, auth failure, misconfigured provider), the error is wrapped as this SYSTEM-category MastraError. This differs from 1056: here the lease backend errored, rather than reporting the lease as held by someone else.","triggerScenarios":"Calling agent.recover(runId) when the configured LeaseProvider's backend is unavailable or misconfigured — e.g. Redis/DB connection failure, invalid credentials, network partition — so acquireLease() throws instead of returning { acquired: false }.","commonSituations":"Lease provider (Redis/Postgres) down or unreachable from the deployment; wrong connection string/env vars in the new environment; firewall blocking the lease store; transient network blip during a recovery burst.","solutions":["Inspect the `cause` on the thrown error to find the underlying lease-provider failure (connection, auth, timeout).","Verify the LeaseProvider configuration and connectivity (connection string, credentials, network access) and re-run recover().","Retry with backoff if the backend failure was transient.","If no external lease store is intended, check why a real provider was configured instead of NoopLeaseProvider."],"exampleFix":"// before\nawait agent.recover(runId); // fails when Redis is down\n// after\ntry {\n  await agent.recover(runId);\n} catch (e) {\n  if (e?.id === 'DURABLE_AGENT_RECOVER_LEASE_ACQUIRE_FAILED') {\n    await checkLeaseStoreHealth(); // verify/restore Redis, then retry\n    await agent.recover(runId);\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"await leaseProviderHealthy(); // ping/health-check Redis/DB before starting recovery batches","typeGuard":null,"tryCatchPattern":"try {\n  await agent.recover(runId);\n} catch (e) {\n  if (String(e?.id) === 'DURABLE_AGENT_RECOVER_LEASE_ACQUIRE_FAILED') {\n    await backoffRetry(() => agent.recover(runId), { attempts: 3 }); // transient backend failure\n  } else throw e;\n}","preventionTips":["Health-check the lease store (Redis/Postgres) as part of startup and before recovery batches.","Validate lease-provider connection config (URLs, credentials, network) per environment.","Alert on lease-store outages; add exponential backoff for lease operations."],"tags":["durable-agent","recovery","lease","network","backend","system"],"backgroundTag":"lease-acquire-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}