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" with a lease acquired on the wrong resource.

What it means

validateAcquiredLease() also checks that the acquired lease's resourcePHID equals the PHID of the resource it was acquired against. A mismatch means the blueprint acquired the lease on a different resource than the one the worker selected, breaking the pairing between lease and resource. The blueprint must acquire on exactly the $resource passed in.

Source

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

    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(),
          'acquireLease()'));
    }
  }


/* -(  Activating Leases  )-------------------------------------------------- */


  /**
   * @task activate
   */
  private function activateLease(DrydockLease $lease) {
    $resource = $lease->getResource();

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use the $resource parameter passed to acquireLease(); do not reload or re-select a resource inside the blueprint.
  2. If the blueprint needs related objects, attach them to the passed resource instead of substituting another one.
  3. Assert $lease->getResourcePHID() === $resource->getPHID() in development builds.

Example fix

// before
public function acquireLease(DrydockResource $resource, DrydockLease $lease) {
  $host = $this->loadAnyHostResource(); // different resource!
  $host->acquireLease($lease);
}

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

Strategy: validation

Validate before calling

if ($lease->getResourcePHID() !== $resource->getPHID()) {
  throw new Exception(
    pht('Lease acquired on resource "%s", expected "%s".',
      $lease->getResourcePHID(), $resource->getPHID()));
}

Prevention

When it happens

Trigger: Blueprint acquireLease() that loads its own resource (e.g. by attribute lookup or getBlueprint() query) and calls acquireLease() on that object instead of the passed $resource; reusing a cached resource object from a previous allocation.

Common situations: Blueprint queries for 'a free host' internally rather than using the resource the allocator chose; copied code from a single-resource blueprint where hardcoding happened to work.

Related errors


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