phacility/phabricator · error · Exception

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

Error message

Blueprint "%s" (of type "%s") is not properly implemented: %s must return an object of type %s or throw, but returned something else.

What it means

After a blueprint's allocateResource() returns, DrydockLeaseUpdateWorker::validateAllocatedResource() checks that the returned value is actually a DrydockResource. Anything else (null, an array, an unrelated object) means the blueprint broke its contract: it must return the allocated resource or throw. This is a bug in blueprint code, not in the caller or configuration.

Source

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


  /**
   * Check that the resource a blueprint allocated is roughly the sort of
   * object we expect.
   *
   * @param DrydockBlueprint Blueprint which built the resource.
   * @param wild Thing which the blueprint claims is a valid resource.
   * @param DrydockLease Lease the resource was allocated for.
   * @return void
   * @task allocator
   */
  private function validateAllocatedResource(
    DrydockBlueprint $blueprint,
    $resource,
    DrydockLease $lease) {

    if (!($resource instanceof DrydockResource)) {
      throw new Exception(
        pht(
          'Blueprint "%s" (of type "%s") is not properly implemented: %s must '.
          'return an object of type %s or throw, but returned something else.',
          $blueprint->getBlueprintName(),
          $blueprint->getClassName(),
          'allocateResource()',
          'DrydockResource'));
    }

    if (!$resource->isAllocatedResource()) {
      throw new Exception(
        pht(
          'Blueprint "%s" (of type "%s") is not properly implemented: %s '.
          'must actually allocate the resource it returns.',
          $blueprint->getBlueprintName(),
          $blueprint->getClassName(),
          'allocateResource()'));
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Make allocateResource() return the DrydockResource produced by newResourceTemplate() after calling $resource->allocateResource().
  2. Add a return-type check in development: `if (!$resource instanceof DrydockResource) throw ...` before returning.
  3. Compare against DrydockWorkingCopyBlueprintImplementation::allocateResource() for the canonical shape.

Example fix

// before
public function allocateResource(DrydockBlueprint $blueprint, DrydockLease $lease) {
  $this->provisionHost($blueprint);
  // forgot to return the resource -> returns null
}

// after
public function allocateResource(DrydockBlueprint $blueprint, DrydockLease $lease) {
  $this->provisionHost($blueprint);
  return $this->newResourceTemplate($blueprint)->allocateResource();
}
Defensive patterns

Strategy: type-guard

Type guard

function isDrydockResource($value) {
  return $value instanceof DrydockResource;
}

Prevention

When it happens

Trigger: A custom allocateResource() that forgets `return $resource;` on its success path (returns null); returning a template/DTO array or a PhabricatorObject instead of the DrydockResource; an early return on a path that skipped creating the resource.

Common situations: First draft of a custom blueprint; refactoring a blueprint and dropping the return statement; copying working-copy blueprint code and trimming too much.

Related errors


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