{"record":{"id":"7d7dc3f296c11902","repo":"phacility/phabricator","slug":"subtype-configuration-is-invalid-subtype-with-key-7d7dc3","errorCode":null,"errorMessage":"Subtype configuration is invalid: subtype with key \"%s\" specifies that it can mutate into subtype \"%s\", but that is not a valid subtype.","messagePattern":"Subtype configuration is invalid: subtype with key \"(.+?)\" specifies that it can mutate into subtype \"(.+?)\", but that is not a valid subtype\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php","lineNumber":246,"sourceCode":"    if (!isset($map[self::SUBTYPE_DEFAULT])) {\n      throw new Exception(\n        pht(\n          'Subtype configuration is invalid: there is no subtype defined '.\n          'with key \"%s\". This subtype is required and must be defined.',\n          self::SUBTYPE_DEFAULT));\n    }\n\n    foreach ($config as $value) {\n      $key = idx($value, 'key');\n\n      $mutations = idx($value, 'mutations');\n      if (!$mutations) {\n        continue;\n      }\n\n      foreach ($mutations as $mutation) {\n        if (!isset($map[$mutation])) {\n          throw new Exception(\n            pht(\n              'Subtype configuration is invalid: subtype with key \"%s\" '.\n              'specifies that it can mutate into subtype \"%s\", but that is '.\n              'not a valid subtype.',\n              $key,\n              $mutation));\n        }\n      }\n    }\n\n  }\n\n  public static function newSubtypeMap(array $config) {\n    $map = array();\n\n    foreach ($config as $entry) {\n      $key = $entry['key'];\n      $name = $entry['name'];","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php#L228-L264","documentation":"Phabricator EditEngine subtypes may declare a 'mutations' list naming the subtype keys an object is allowed to change into. When the subtype map is built, every mutation target is checked against the set of configured subtype keys ($map). This exception means a subtype's 'mutations' entry references a key that is not defined in the same 'subtypes' configuration.","triggerScenarios":"An EditEngine subtype config (e.g. maniphest.subtypes set via application settings or maniphest.edit-engine config) contains an entry like {\"key\": \"bug\", \"mutations\": [\"defect\"]} where \"defect\" is not one of the configured subtype keys. The check runs whenever PhabricatorEditEngineSubtype parses the config, i.e. whenever subtype UI or a subtype transaction is used.","commonSituations":"Renaming or removing a subtype key while forgetting to update 'mutations' lists that still point at the old key; copy-pasting subtype config between applications whose key sets differ; typos in JSON config; stale cache masking the real config after an edit.","solutions":["Open the subtype config (e.g. Config -> Maniphest -> maniphest.subtypes, or the application's edit-engine config) and fix every 'mutations' entry so it names an existing subtype 'key' from the same list.","If the target subtype was intentionally removed, delete it from all 'mutations' lists.","Run 'bin/cache clear' after changing config so the parsed subtype map is rebuilt.","Before deploying, validate the config in a scratch script by calling PhabricatorEditEngineSubtype parsing in a try/catch."],"exampleFix":"// before (subtype config JSON)\n[\n  {\"key\": \"bug\", \"name\": \"Bug\", \"mutations\": [\"defect\"]},\n  {\"key\": \"feature\", \"name\": \"Feature\"}\n]\n\n// after\n[\n  {\"key\": \"bug\", \"name\": \"Bug\", \"mutations\": [\"feature\"]},\n  {\"key\": \"feature\", \"name\": \"Feature\"}\n]","handlingStrategy":"validation","validationCode":"// Validate subtype config before deploy / after edits\n$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');\n$keys = array_fuse(ipull($config, null, 'key'));\nforeach ($config as $subtype) {\n  foreach (idx($subtype, 'mutations', array()) as $target) {\n    if (!isset($keys[$target])) {\n      throw new Exception(\n        pht('Subtype \"%s\" mutates to undefined key \"%s\".',\n          $subtype['key'], $target));\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  $map = PhabricatorEditEngineSubtype::newSubtypes($engine);\n} catch (Exception $ex) {\n  // Surface a config error instead of a broken edit UI\n  return $this->newDialog()->setTitle(pht('Invalid Subtype Config'))\n    ->appendChild($ex->getMessage());\n}","preventionTips":["Keep every 'mutations' list synchronized with the current set of subtype keys; update both in the same change.","Add a config-lint step to deployment that parses subtype configuration in a try/catch.","Avoid renaming subtype keys unless you grep the config for references first."],"tags":["phabricator","editengine","subtype","config-validation","php"],"backgroundTag":"config-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}