{"record":{"id":"ebac6e5b5ecff561","repo":"phacility/phabricator","slug":"trying-to-allocate-a-resource-with-no-generated-ph","errorCode":null,"errorMessage":"Trying to allocate a resource with no generated PHID. Use \"%s\" to create new resource templates.","messagePattern":"Trying to allocate a resource with no generated PHID\\. Use \"(.+?)\" to create new resource templates\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/storage/DrydockResource.php","lineNumber":121,"sourceCode":"\n    return false;\n  }\n\n  public function setActivateWhenAllocated($activate) {\n    $this->activateWhenAllocated = $activate;\n    return $this;\n  }\n\n  public function needSlotLock($key) {\n    $this->slotLocks[] = $key;\n    return $this;\n  }\n\n  public function allocateResource() {\n    // We expect resources to have a pregenerated PHID, as they should have\n    // been created by a call to DrydockBlueprint->newResourceTemplate().\n    if (!$this->getPHID()) {\n      throw new Exception(\n        pht(\n          'Trying to allocate a resource with no generated PHID. Use \"%s\" to '.\n          'create new resource templates.',\n          'newResourceTemplate()'));\n    }\n\n    $expect_status = DrydockResourceStatus::STATUS_PENDING;\n    $actual_status = $this->getStatus();\n    if ($actual_status != $expect_status) {\n      throw new Exception(\n        pht(\n          'Trying to allocate a resource from the wrong status. Status must '.\n          'be \"%s\", actually \"%s\".',\n          $expect_status,\n          $actual_status));\n    }\n\n    if ($this->activateWhenAllocated) {","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/storage/DrydockResource.php#L103-L139","documentation":"Drydock resources must be created through DrydockBlueprintImplementation::newResourceTemplate(), which builds the object, generates its PHID, and sets status PENDING. allocateResource() then persists it and runs the allocation lifecycle. If allocateResource() is called on a resource object lacking a PHID (i.e. constructed directly via new DrydockResource() or saved without a PHID), the allocator refuses: persisted Drydock objects are keyed by PHID and the allocation bookkeeping depends on it. This is a pure programmer error in blueprint implementation code.","triggerScenarios":"Custom blueprint code doing `id(new DrydockResource())->save()` then `->allocateResource()`; copying an allocated resource object and trying to re-allocate the clone; bypassing newResourceTemplate() because it is protected on the implementation class.","commonSituations":"Writing a first custom DrydockBlueprintImplementation; refactoring stock blueprints and dropping the template call; test scaffolding that constructs resources directly.","solutions":["Create resources via the template API inside your implementation: `$resource = $this->newResourceTemplate($blueprint);` then configure and `$resource->allocateResource()`","Never call `new DrydockResource()` directly in allocation paths — the constructor does not generate a PHID","If porting old blueprint code from an earlier Drydock version, update to the newResourceTemplate() pattern introduced with the rewritten allocator","Check that you are not re-using an already-saved resource object for a second allocation"],"exampleFix":"// before\n$resource = new DrydockResource();\n$resource->setBlueprintPHID($blueprint->getPHID());\n$resource->allocateResource();\n// Exception: Trying to allocate a resource with no generated PHID...\n\n// after\n$resource = $this->newResourceTemplate($blueprint);\n$resource->allocateResource();","handlingStrategy":"validation","validationCode":"// Assert the template is properly initialized before allocation:\nif (!$resource->getPHID()) {\n  throw new Exception(pht(\n    'Build resources with newResourceTemplate(), not new DrydockResource().'));\n}\n$resource->allocateResource();","typeGuard":"// Guard: a allocatable template has a PHID and PENDING status.\nfunction isAllocatableTemplate(DrydockResource $resource) {\n  return (bool)$resource->getPHID();\n}","tryCatchPattern":"catch (Exception $ex) { on 'no generated PHID', replace direct construction with $this->newResourceTemplate($blueprint) inside the blueprint implementation; nothing else makes the object allocatable }","preventionTips":["Always create resources through newResourceTemplate() in DrydockBlueprintImplementation subclasses","Never call new DrydockResource() in allocation code paths","Lint custom blueprints for direct resource construction during code review"],"tags":["drydock","phabricator","resource","blueprint","programmer-error","template-api"],"backgroundTag":"uninitialized-object-state","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}