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 activating a lease.

What it means

After the blueprint activates a lease, validateActivatedLease() checks isActivatedLease(), which only becomes true when DrydockLease::activateLease() runs. A normal return without that call violates the blueprint contract: activateLease() must activate the lease or throw. Note the message text in this version says 'acquireLease()' but the check guards the activation step.

Source

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

    // be distinguishable from a resource dying right after we activate a lease
    // on it. We end up with an active lease on a dead resource either way, and
    // can not prevent resources dying from lightning strikes.

    $blueprint = $resource->getBlueprint();
    $blueprint->activateLease($resource, $lease);
    $this->validateActivatedLease($blueprint, $resource, $lease);
  }

  /**
   * @task activate
   */
  private function validateActivatedLease(
    DrydockBlueprint $blueprint,
    DrydockResource $resource,
    DrydockLease $lease) {

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

  }


/* -(  Releasing Leases  )--------------------------------------------------- */


  /**
   * @task release
   */
  private function releaseLease(DrydockLease $lease) {

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Call $lease->activateLease() on every success path of the blueprint's activateLease().
  2. Throw instead of returning when activation cannot complete.
  3. Follow DrydockWorkingCopyBlueprintImplementation's activation flow as a template.

Example fix

// before
public function activateLease(DrydockResource $resource, DrydockLease $lease) {
  $this->prepareDirectory($resource);
  // missing $lease->activateLease()
}

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

Strategy: validation

Validate before calling

if (!$lease->isActivatedLease()) {
  throw new Exception(
    pht('activateLease() returned without activating; call $lease->activateLease().'));
}

Prevention

When it happens

Trigger: Custom blueprint's activateLease() performs its setup (bootstrapping a working directory, writing credentials) but never calls $lease->activateLease(); an early return on a branch where activation was skipped.

Common situations: Writing the activation half of a custom blueprint; refactoring that moves the activate call into an exception path only.

Related errors


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