phacility/phabricator · error · Exception

Blueprint "%s" (of type "%s") is not properly implemented: i

Error message

Blueprint "%s" (of type "%s") is not properly implemented: it returned from "%s" without acquiring a lease.

What it means

After DrydockLeaseUpdateWorker calls $blueprint->acquireLease($resource, $lease), validateAcquiredLease() verifies the lease actually transitioned to acquired (isAcquiredLease() is set by DrydockLease::acquireLease()). If the blueprint returns normally without acquiring, it violated the contract: acquireLease() must either acquire the lease or throw. The lease would otherwise sit forever in an inconsistent state.

Source

Thrown at src/applications/drydock/worker/DrydockLeaseUpdateWorker.php:946

  }


  /**
   * Make sure that a lease was really acquired properly.
   *
   * @param DrydockBlueprint Blueprint which created the resource.
   * @param DrydockResource Resource which was acquired.
   * @param DrydockLease The lease which was supposedly acquired.
   * @return void
   * @task acquire
   */
  private function validateAcquiredLease(
    DrydockBlueprint $blueprint,
    DrydockResource $resource,
    DrydockLease $lease) {

    if (!$lease->isAcquiredLease()) {
      throw new Exception(
        pht(
          'Blueprint "%s" (of type "%s") is not properly implemented: it '.
          'returned from "%s" without acquiring a lease.',
          $blueprint->getBlueprintName(),
          $blueprint->getClassName(),
          'acquireLease()'));
    }

    $lease_phid = $lease->getResourcePHID();
    $resource_phid = $resource->getPHID();

    if ($lease_phid !== $resource_phid) {
      throw new Exception(
        pht(
          'Blueprint "%s" (of type "%s") is not properly implemented: it '.
          'returned from "%s" with a lease acquired on the wrong resource.',
          $blueprint->getBlueprintName(),
          $blueprint->getClassName(),

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Call $lease->acquireLease() (and save) inside the blueprint's acquireLease() before returning.
  2. Throw on any path where the lease cannot be acquired rather than returning silently.
  3. Model the implementation on DrydockWorkingCopyBlueprintImplementation::acquireLease().

Example fix

// before
public function acquireLease(DrydockResource $resource, DrydockLease $lease) {
  $this->reserveSlot($resource);
  // no $lease->acquireLease() -> validator throws
}

// after
public function acquireLease(DrydockResource $resource, DrydockLease $lease) {
  $this->reserveSlot($resource);
  $lease->acquireLease();
}
Defensive patterns

Strategy: validation

Validate before calling

if (!$lease->isAcquiredLease()) {
  throw new Exception(
    pht('acquireLease() returned without acquiring; call $lease->acquireLease().'));
}

Prevention

When it happens

Trigger: Custom acquireLease() that does setup work (writes credentials, reserves a slot) but forgets to call $lease->acquireLease(); an early return on a path that decides not to lease instead of throwing.

Common situations: First implementation of a custom blueprint's acquireLease(); refactoring that extracts the acquire call into a helper that is bypassed on one branch.

Related errors


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