{"record":{"id":"c95e2ba9141a13f2","repo":"phacility/phabricator","slug":"when-creating-a-new-drydock-blueprint-via-the-cond","errorCode":null,"errorMessage":"When creating a new Drydock blueprint via the Conduit API, you must provide a \"type\" transaction to select a type.","messagePattern":"When creating a new Drydock blueprint via the Conduit API, you must provide a \"type\" transaction to select a type\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/drydock/editor/DrydockBlueprintEditEngine.php","lineNumber":65,"sourceCode":"        ->setClassName(get_class($impl))\n        ->attachImplementation(clone $impl);\n    }\n\n    return $blueprint;\n  }\n\n  protected function newEditableObjectFromConduit(array $raw_xactions) {\n    $type = null;\n    foreach ($raw_xactions as $raw_xaction) {\n      if ($raw_xaction['type'] !== 'type') {\n        continue;\n      }\n\n      $type = $raw_xaction['value'];\n    }\n\n    if ($type === null) {\n      throw new Exception(\n        pht(\n          'When creating a new Drydock blueprint via the Conduit API, you '.\n          'must provide a \"type\" transaction to select a type.'));\n    }\n\n    $map = DrydockBlueprintImplementation::getAllBlueprintImplementations();\n    if (!isset($map[$type])) {\n      throw new Exception(\n        pht(\n          'Blueprint type \"%s\" is unrecognized. Valid types are: %s.',\n          $type,\n          implode(', ', array_keys($map))));\n    }\n\n    $impl = clone $map[$type];\n    $this->setBlueprintImplementation($impl);\n\n    return $this->newEditableObject();","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/drydock/editor/DrydockBlueprintEditEngine.php#L47-L83","documentation":"Thrown by DrydockBlueprintEditEngine::newEditableObjectFromConduit() when a Conduit 'drydock.blueprint.edit' call creates a new blueprint without a transaction of type 'type'. Blueprint type cannot be inferred or defaulted because the concrete DrydockBlueprintImplementation must be selected before the object can even be constructed, so the edit engine requires exactly one 'type' transaction in the raw transaction list for creates.","triggerScenarios":"Calling drydock.blueprint.edit with a transactions array that contains only field edits (e.g. [{'type': 'name', 'value': '...'}]) and no {'type': 'type', 'value': ...} entry, without passing an object identifier (i.e. a create, not an edit). The loop over $raw_xactions leaves $type === null and the exception fires.","commonSituations":"Porting a script from another application's *.edit Conduit method where type is optional; building blueprints programmatically in setup automation and forgetting the type; sending the type under a wrong transaction name (e.g. 'blueprint-type' or 'class').","solutions":["Add a type transaction as the first entry: {'type': 'type', 'value': 'host'} (or another registered blueprint type), then re-issue the Conduit call.","Check the transaction name spelling — it must be exactly the literal string 'type'.","For subsequent edits of an existing blueprint, pass its object identifier (id/phid) so the call no longer needs the type transaction."],"exampleFix":"// before\n$result = $client->callMethodSynchronous(\n  'drydock.blueprint.edit',\n  array(\n    'transactions' => array(\n      array('type' => 'name', 'value' => 'Host Blueprint'),\n    ),\n  ));\n\n// after\n$result = $client->callMethodSynchronous(\n  'drydock.blueprint.edit',\n  array(\n    'transactions' => array(\n      array('type' => 'type', 'value' => 'host'),\n      array('type' => 'name', 'value' => 'Host Blueprint'),\n    ),\n  ));","handlingStrategy":"validation","validationCode":"$has_type = false;\nforeach ($transactions as $xaction) {\n  if ($xaction['type'] === 'type' && idx($xaction, 'value') !== null) {\n    $has_type = true;\n  }\n}\nif (!$has_type && $object_identifier === null) {\n  throw new InvalidArgumentException(\n    'Blueprint creation via Conduit requires a type transaction.');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap drydock.blueprint.edit calls in a helper that always injects the type transaction for creates.","Remember creates need 'type'; edits of an existing blueprint (with object id/phid) do not."],"tags":["drydock","phabricator","conduit","api","blueprint","edit-engine"],"backgroundTag":"missing-required-parameter","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}