{"record":{"id":"64647d0ac2d09674","repo":"phacility/phabricator","slug":"trying-to-acquire-an-active-lease-on-a-pending-res","errorCode":null,"errorMessage":"Trying to acquire an active lease on a pending resource. You can not immediately activate leases on resources which need time to start up.","messagePattern":"Trying to acquire an active lease on a pending resource\\. You can not immediately activate leases on resources which need time to start up\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/storage/DrydockLease.php","lineNumber":236,"sourceCode":"    $actual_status = $this->getStatus();\n    if ($actual_status != $expect_status) {\n      throw new Exception(\n        pht(\n          'Trying to acquire a lease on a resource which is in the wrong '.\n          'state: status must be \"%s\", actually \"%s\".',\n          $expect_status,\n          $actual_status));\n    }\n\n    if ($this->activateWhenAcquired) {\n      $new_status = DrydockLeaseStatus::STATUS_ACTIVE;\n    } else {\n      $new_status = DrydockLeaseStatus::STATUS_ACQUIRED;\n    }\n\n    if ($new_status == DrydockLeaseStatus::STATUS_ACTIVE) {\n      if ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {\n        throw new Exception(\n          pht(\n            'Trying to acquire an active lease on a pending resource. '.\n            'You can not immediately activate leases on resources which '.\n            'need time to start up.'));\n      }\n    }\n\n    // Before we associate the lease with the resource, we lock the resource\n    // and reload it to make sure it is still pending or active. If we don't\n    // do this, the resource may have just been reclaimed. (Once we acquire\n    // the resource that stops it from being released, so we're nearly safe.)\n\n    $resource_phid = $resource->getPHID();\n    $hash = PhabricatorHash::digestForIndex($resource_phid);\n    $lock_key = 'drydock.resource:'.$hash;\n    $lock = PhabricatorGlobalLock::newLock($lock_key);\n\n    try {","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/storage/DrydockLease.php#L218-L254","documentation":"A lease can request immediate activation (activateWhenAcquired) so that acquisition and activation happen in one step, giving callers a ready-to-use ACTIVE lease. That is only legal if the resource it lands on is already past startup: acquiring-and-activating onto a resource still in STATUS_PENDING would promise an interface that does not exist yet, so acquireOnResource() refuses. Resources that allocate asynchronously (hosts that take time to boot) routinely sit in PENDING, making this a normal outcome of requesting immediate activation.","triggerScenarios":"Creating a lease with setActivateWhenAcquired(true) (or the equivalent force-activation flag) and having the allocator select a freshly-created, still-PENDING resource; racing a resource that is allocated and leased in the same breath before the resource's own activation worker runs.","commonSituations":"Build systems that want a usable lease synchronously; host blueprints with slow provisioning (Almanac service hosts) where the resource stays PENDING for a while; tests that allocate and lease in one transaction.","solutions":["Do not force immediate activation: acquire normally (two-phase), then trigger activation via the lease update worker once the resource becomes ACTIVE","Have the allocator prefer resources already in STATUS_ACTIVE when the lease demands immediate activation","If you control resource allocation, set activateWhenAllocated on the resource so it is ACTIVE before leases attach","Retry land/lease request after the resource activation worker completes — the pending window is transient"],"exampleFix":"// before\n$lease = $blueprint->newLease()\n  ->setActivateWhenAcquired(true) // immediate activation\n  ->queueForActivation();\n// allocator picks a pending resource -> Exception\n\n// after\n$lease = $blueprint->newLease()\n  // two-phase: acquire now, activate when resource is ready\n  ->queueForActivation();","handlingStrategy":"validation","validationCode":"// Only request immediate activation when the resource is already ACTIVE:\n$immediate = ($resource->getStatus() === DrydockResourceStatus::STATUS_ACTIVE);\n$lease = $blueprint->newLease();\nif ($immediate) {\n  $lease->setActivateWhenAcquired(true);\n}\n$lease->queueForActivation();","typeGuard":null,"tryCatchPattern":"catch (Exception $ex) { on 'active lease on a pending resource', fall back to two-phase: acquire without immediate activation and let the lease update worker activate once the resource boots }","preventionTips":["Default to two-phase acquire-then-activate; use activateWhenAcquired only with known-ACTIVE resources","Prefer blueprints that set activateWhenAllocated on resources when synchronous leases are required","Design consumers to poll/wait for lease ACTIVation rather than expecting it synchronously"],"tags":["drydock","phabricator","lease","resource-lifecycle","pending-resource","activation"],"backgroundTag":"dependency-not-ready","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}