{"record":{"id":"8b9374dd84f3482f","repo":"phacility/phabricator","slug":"blueprint-s-of-type-s-is-not-properly-impl-8b9374","errorCode":null,"errorMessage":"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\".","messagePattern":"Blueprint \"(.+?)\" \\(of type \"(.+?)\"\\) is not properly implemented: it built a resource of type \"(.+?)\" to satisfy a lease requesting a resource of type \"(.+?)\"\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/worker/DrydockLeaseUpdateWorker.php","lineNumber":854,"sourceCode":"          'allocateResource()',\n          'DrydockResource'));\n    }\n\n    if (!$resource->isAllocatedResource()) {\n      throw new Exception(\n        pht(\n          'Blueprint \"%s\" (of type \"%s\") is not properly implemented: %s '.\n          'must actually allocate the resource it returns.',\n          $blueprint->getBlueprintName(),\n          $blueprint->getClassName(),\n          'allocateResource()'));\n    }\n\n    $resource_type = $resource->getType();\n    $lease_type = $lease->getResourceType();\n\n    if ($resource_type !== $lease_type) {\n      throw new Exception(\n        pht(\n          'Blueprint \"%s\" (of type \"%s\") is not properly implemented: it '.\n          'built a resource of type \"%s\" to satisfy a lease requesting a '.\n          'resource of type \"%s\".',\n          $blueprint->getBlueprintName(),\n          $blueprint->getClassName(),\n          $resource_type,\n          $lease_type));\n    }\n  }\n\n  private function reclaimResources(\n    DrydockBlueprint $blueprint,\n    DrydockLease $lease) {\n    $viewer = $this->getViewer();\n\n    $resources = id(new DrydockResourceQuery())\n      ->setViewer($viewer)","sourceCodeStart":836,"sourceCodeEnd":872,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php#L836-L872","documentation":"The third validation in validateAllocatedResource() compares the built resource's getType() with the lease's getResourceType(); they must be identical strings. The blueprint claimed to serve the lease's type but constructed a resource of a different type, so the lease could never use it. This is a blueprint implementation bug, typically a hardcoded or mismatched type string.","triggerScenarios":"A custom allocateResource() that calls newResourceTemplate() with a fixed type like 'host' while the lease requested 'working-copy'; a blueprint implementation whose getType() was renamed but the template creation still uses the old literal; differing casing or spelling between the two strings.","commonSituations":"One blueprint implementation reused to build several resource types; type renames across Phabricator versions; copy-paste between host and working-copy blueprints.","solutions":["Create the template with exactly the lease's type: $this->newResourceTemplate() with getType() matching $lease->getResourceType().","Use $this->getType() (the implementation's declared type) as the single source of truth instead of string literals.","Check for casing/whitespace differences between the blueprint type and the lease's requested resource type."],"exampleFix":"// before\n$resource = $this->newResourceTemplate($blueprint)\n  ->setAttribute('type', 'host'); // blueprint serves 'working-copy'\n\n// after\n$resource = $this->newResourceTemplate($blueprint); // type comes from getType(), matches lease","handlingStrategy":"validation","validationCode":"if ($resource->getType() !== $lease->getResourceType()) {\n  throw new Exception(\n    pht('Blueprint built \"%s\" for a lease of type \"%s\".',\n      $resource->getType(), $lease->getResourceType()));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive template types from $this->getType(); never hardcode type literals in blueprints.","Share one type constant between the code that creates leases and the blueprint implementation."],"tags":["drydock","php","blueprint","contract","type-mismatch"],"backgroundTag":"resource-type-mismatch","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}