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 actually allocate the resource it returns.

What it means

validateAllocatedResource() also checks the returned resource was actually allocated: DrydockResource::allocateResource() sets the in-process isAllocated flag after acquiring slot locks and saving. If the flag is false, the blueprint returned a resource object without ever calling allocateResource() on it, so it was never persisted or locked. The object the blueprint hands back is not a real, usable resource.

Source

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

   */
  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()'));
    }

    $resource_type = $resource->getType();
    $lease_type = $lease->getResourceType();

    if ($resource_type !== $lease_type) {
      throw new Exception(
        pht(
          'Blueprint "%s" (of type "%s") is not properly implemented: it '.
          'built a resource of type "%s" to satisfy a lease requesting a '.
          'resource of type "%s".',
          $blueprint->getBlueprintName(),

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Call $resource->allocateResource() before returning it from allocateResource(); that call persists the row and acquires its slot locks.
  2. Make sure the call is unconditional on the success path; on failure, throw instead of returning an unallocated template.
  3. Follow the pattern in DrydockWorkingCopyBlueprintImplementation::allocateResource().

Example fix

// before
$resource = $this->newResourceTemplate($blueprint);
$resource->setAttribute('host', $host);
return $resource; // never allocated

// after
$resource = $this->newResourceTemplate($blueprint);
$resource->setAttribute('host', $host);
return $resource->allocateResource();
Defensive patterns

Strategy: validation

Validate before calling

if (!$resource->isAllocatedResource()) {
  throw new Exception(
    pht('allocateResource() returned before allocating; call $resource->allocateResource().'));
}

Prevention

When it happens

Trigger: Custom allocateResource() that creates a template with newResourceTemplate(), sets some attributes, and returns it without calling $resource->allocateResource(); calling allocateResource() conditionally and returning on the skipped branch.

Common situations: Blueprint author assumes the worker does the allocation; refactor moves the allocateResource() call behind an if that is false in the tested path; porting an old blueprint written before allocation became explicit.

Related errors


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