{"record":{"id":"3a3e0483ea190ffb","repo":"phacility/phabricator","slug":"trying-to-activate-a-lease-on-a-pending-resource","errorCode":null,"errorMessage":"Trying to activate a lease on a pending resource.","messagePattern":"Trying to activate a lease on a pending resource\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/storage/DrydockLease.php","lineNumber":343,"sourceCode":"  public function isAcquiredLease() {\n    return $this->isAcquired;\n  }\n\n  public function activateOnResource(DrydockResource $resource) {\n    $expect_status = DrydockLeaseStatus::STATUS_ACQUIRED;\n    $actual_status = $this->getStatus();\n    if ($actual_status != $expect_status) {\n      throw new Exception(\n        pht(\n          'Trying to activate a lease which has the wrong status: status '.\n          'must be \"%s\", actually \"%s\".',\n          $expect_status,\n          $actual_status));\n    }\n\n    if ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {\n      // TODO: Be stricter about this?\n      throw new Exception(\n        pht(\n          'Trying to activate a lease on a pending resource.'));\n    }\n\n    $this->openTransaction();\n\n    try {\n      DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);\n      $this->slotLocks = array();\n    } catch (DrydockSlotLockException $ex) {\n      $this->killTransaction();\n\n      $this->logEvent(\n        DrydockSlotLockFailureLogType::LOGCONST,\n        array(\n          'locks' => $ex->getLockMap(),\n        ));\n","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/storage/DrydockLease.php#L325-L361","documentation":"Activation gives a lease a live interface, which is only meaningful once the underlying resource has finished starting up; activating against a resource still in STATUS_PENDING is refused (the code even carries a TODO about being stricter). Unlike the wrong-lease-status variants, this condition is often transient: the resource will typically move PENDING → ACTIVE via its update worker, after which activation succeeds. The stock lease worker yields and retries in this situation.","triggerScenarios":"Two-phase leases (acquire then activate) where activation runs before the resource's boot/provisioning completes; host blueprints with slow startup; queuing activation immediately after acquiring on a resource allocated moments earlier.","commonSituations":"Working-copy leases on freshly allocated hosts; build queues that try to activate leases during infrastructure cold-start; tests that skip waiting for resource activation.","solutions":["Wait for the resource to reach STATUS_ACTIVE (poll its status or let the lease update worker retry) before activating the lease","Trigger the resource's update worker (`./bin/drydock update-resource --id <n>`) to force it through pending","Check the resource log/blueprint log for why provisioning is stalled in PENDING — that is the real problem when the wait never ends","If the resource is permanently pending due to a blueprint failure, release the lease and resource and re-allocate"],"exampleFix":"// before\n$lease->activateOnResource($resource); // resource still STATUS_PENDING\n// Exception: Trying to activate a lease on a pending resource.\n\n// after\n$resource = $resource->reload();\nwhile ($resource->getStatus() === DrydockResourceStatus::STATUS_PENDING) {\n  sleep(5); // or yield the worker task and retry later\n  $resource = $resource->reload();\n}\n$lease->activateOnResource($resource);","handlingStrategy":"retry","validationCode":"// Before activating, confirm the resource has finished starting up:\n$resource = $resource->reload();\nif ($resource->getStatus() === DrydockResourceStatus::STATUS_PENDING) {\n  // not ready yet: schedule retry / trigger the resource update worker\n  throw new PhabricatorWorkerYieldException(15);\n}\n$lease->activateOnResource($resource);","typeGuard":null,"tryCatchPattern":"catch (Exception $ex) { on 'pending resource', catch DrydockResourceLockException-style yielding: wait for the resource update worker to move it to ACTIVE, then retry activation with freshly loaded objects }","preventionTips":["Treat resource startup as asynchronous: poll status or yield/retry, never assume immediate readiness","Force a stalled resource through its update with ./bin/drydock update-resource --id <n>","Alert on resources stuck in PENDING — a lease failing here is usually a symptom of a stuck blueprint, not a lease bug"],"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"}