{"record":{"id":"62e739e03891f4da","repo":"phacility/phabricator","slug":"lease-has-already-been-released","errorCode":null,"errorMessage":"Lease has already been released!","messagePattern":"Lease has already been released!","errorType":"console","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/management/DrydockManagementLeaseWorkflow.php","lineNumber":248,"sourceCode":"          $type = pht('Unknown (\"%s\")', $type_key);\n          $data = null;\n        }\n\n        echo tsprintf(\n          \"(Lease #%d) <%s> %B\\n\",\n          $lease->getID(),\n          $type,\n          $data);\n      }\n\n      $status = $lease->getStatus();\n\n      switch ($status) {\n        case DrydockLeaseStatus::STATUS_ACTIVE:\n          $is_active = true;\n          break;\n        case DrydockLeaseStatus::STATUS_RELEASED:\n          throw new Exception(pht('Lease has already been released!'));\n        case DrydockLeaseStatus::STATUS_DESTROYED:\n          throw new Exception(pht('Lease has already been destroyed!'));\n        case DrydockLeaseStatus::STATUS_BROKEN:\n          throw new Exception(pht('Lease has been broken!'));\n        case DrydockLeaseStatus::STATUS_PENDING:\n        case DrydockLeaseStatus::STATUS_ACQUIRED:\n          break;\n        default:\n          throw new Exception(\n            pht(\n              'Lease has unknown status \"%s\".',\n              $status));\n      }\n\n      if ($is_active) {\n        break;\n      } else {\n        sleep(1);","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php#L230-L266","documentation":"Thrown by the wait loop in `bin/drydock lease` while polling a lease until it becomes ACTIVE. If the lease's status is STATUS_RELEASED, the command aborts: the lease was released (by another actor, by expiry of its until time, or by a concurrent drydock process) before it could ever activate, so waiting is pointless.","triggerScenarios":"`bin/drydock lease --type host` creates a lease, the CLI polls getStatus(), and some other process (web UI release action, a cleanup daemon, another CLI run, lease expiration) releases it while it is still PENDING/ACQUIRED.","commonSituations":"Two operators/scripts racing on the same lease; a very short --until causing the reaper to release the lease during allocation; the allocation being slow enough that cleanup daemons reap pending leases.","solutions":["Re-run `bin/drydock lease` to acquire a fresh lease once the interfering release source is gone.","Find who released it: check the Drydock log for the lease (Drydock console) for a 'release' actor, and check whether --until was set too aggressively.","If concurrent automation is releasing leases, serialize the acquire/use/release cycle with a lock or unique lease attributes."],"exampleFix":"# before\nbin/drydock lease --type host --until '+30 seconds'  # lease expires mid-allocation\n\n# after\nbin/drydock lease --type host --until '+1 hour'","handlingStrategy":"try-catch","validationCode":"$status = $lease->getStatus();\nif ($status !== DrydockLeaseStatus::STATUS_ACTIVE &&\n    $status !== DrydockLeaseStatus::STATUS_PENDING &&\n    $status !== DrydockLeaseStatus::STATUS_ACQUIRED) {\n  throw new RuntimeException(\n    \"Lease {$lease->getID()} is in terminal status {$status}; re-acquire.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  // acquire + wait for activation (e.g. bin/drydock lease or $lease->waitUntilActive())\n} catch (Exception $ex) {\n  if (preg_match('/already been released/', $ex->getMessage())) {\n    // terminal: log, then re-acquire a fresh lease (single retry)\n    $lease = acquireNewLease($attributes);\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Give --until enough headroom to cover slow allocations.","Ensure only one owner releases a given lease; serialize acquire/use/release in concurrent automation.","Check the lease status in the Drydock console before re-running commands against old lease IDs."],"tags":["drydock","phabricator","lease","state","released","cli"],"backgroundTag":"invalid-resource-state","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}