phacility/phabricator · error · Exception

Trying to acquire a lease on a resource which is in the wron

Error message

Trying to acquire a lease on a resource which is in the wrong state: status must be "%s", actually "%s".

What it means

DrydockLease::acquireOnResource() is the single entry point that moves a lease from PENDING onto a resource, and its precondition is that the lease status is still STATUS_PENDING. Any other status (RELEASED, ACTIVE, ACQUIRED, BROKEN...) means the lease already went through (or skipped) part of its lifecycle, so the state machine refuses with this Exception. This is a programmer/state-machine error, not a transient condition — retrying the same call on the same lease object will fail identically.

Source

Thrown at src/applications/drydock/storage/DrydockLease.php:220

    return $this;
  }

  public function setActivateWhenAcquired($activate) {
    $this->activateWhenAcquired = true;
    return $this;
  }

  public function needSlotLock($key) {
    $this->slotLocks[] = $key;
    return $this;
  }

  public function acquireOnResource(DrydockResource $resource) {
    $expect_status = DrydockLeaseStatus::STATUS_PENDING;
    $actual_status = $this->getStatus();
    if ($actual_status != $expect_status) {
      throw new Exception(
        pht(
          'Trying to acquire a lease on a resource which is in the wrong '.
          'state: status must be "%s", actually "%s".',
          $expect_status,
          $actual_status));
    }

    if ($this->activateWhenAcquired) {
      $new_status = DrydockLeaseStatus::STATUS_ACTIVE;
    } else {
      $new_status = DrydockLeaseStatus::STATUS_ACQUIRED;
    }

    if ($new_status == DrydockLeaseStatus::STATUS_ACTIVE) {
      if ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {
        throw new Exception(
          pht(
            'Trying to acquire an active lease on a pending resource. '.

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Reload the lease from the database immediately before acquiring and confirm status is still DrydockLeaseStatus::STATUS_PENDING
  2. Make sure you acquire each lease exactly once — follow the pattern in DrydockLeaseUpdateWorker::acquireLease()
  3. If the lease already moved to ACQUIRED, call activateOnResource() instead; if RELEASED/BROKEN, create a new lease
  4. Guard custom allocator code against double-entry (yield/retry with a fresh load rather than reusing the in-memory object)

Example fix

// before
$lease->acquireOnResource($resource);
// possibly: status must be "pending", actually "acquired"

// after
$lease = id(new DrydockLeaseQuery())
  ->setViewer($viewer)
  ->withPHIDs(array($lease->getPHID()))
  ->executeOne();
if ($lease->getStatus() !== DrydockLeaseStatus::STATUS_PENDING) {
  return; // already advanced by another worker
}
$lease->acquireOnResource($resource);
Defensive patterns

Strategy: validation

Validate before calling

// Assert lease is still PENDING immediately before acquiring:
$lease = id(new DrydockLeaseQuery())
  ->setViewer($viewer)
  ->withPHIDs(array($lease->getPHID()))
  ->executeOne();
if ($lease->getStatus() !== DrydockLeaseStatus::STATUS_PENDING) {
  // another worker advanced it; skip, don't acquire
}
$lease->acquireOnResource($resource);

Try / catch

catch (Exception $ex) { on 'status must be "pending"', reload the lease: if ACQUIRED continue to activation, if ACTIVE it is done, otherwise (RELEASED/BROKEN) abandon and create a new lease }

Prevention

When it happens

Trigger: Calling acquireOnResource() twice on the same lease object (double allocation in custom allocator code); acquiring a lease that a worker already acquired concurrently; acquiring a lease loaded in a stale state after another process released it.

Common situations: Custom blueprint implementations or Drydock extensions that hand-roll the allocation sequence; retry logic that re-enters acquire with the same lease after a partial failure; reusing a lease object fetched before a daemon processed it.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/9496e5ba0b759a0f. Report an issue: GitHub.