{"record":{"id":"4243e25eb90670a2","repo":"phacility/phabricator","slug":"subtype-configuration-is-invalid-two-subtypes-use","errorCode":null,"errorMessage":"Subtype configuration is invalid: two subtypes use the same key (\"%s\"). Each subtype must have a unique key.","messagePattern":"Subtype configuration is invalid: two subtypes use the same key \\(\"(.+?)\"\\)\\. Each subtype must have a unique key\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php","lineNumber":175,"sourceCode":"    foreach ($config as $value) {\n      PhutilTypeSpec::checkMap(\n        $value,\n        array(\n          'key' => 'string',\n          'name' => 'string',\n          'tag' => 'optional string',\n          'color' => 'optional string',\n          'icon' => 'optional string',\n          'children' => 'optional map<string, wild>',\n          'fields' => 'optional map<string, wild>',\n          'mutations' => 'optional list<string>',\n        ));\n\n      $key = $value['key'];\n      self::validateSubtypeKey($key);\n\n      if (isset($map[$key])) {\n        throw new Exception(\n          pht(\n            'Subtype configuration is invalid: two subtypes use the same '.\n            'key (\"%s\"). Each subtype must have a unique key.',\n            $key));\n      }\n\n      $map[$key] = true;\n\n      $name = $value['name'];\n      if (!strlen($name)) {\n        throw new Exception(\n          pht(\n            'Subtype configuration is invalid: subtype with key \"%s\" has '.\n            'no name. Subtypes must have a name.',\n            $key));\n      }\n\n      $children = idx($value, 'children');","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php#L157-L193","documentation":"While walking the subtype list, validateConfiguration() accumulates seen keys and rejects duplicates: two entries with the same \"key\" make subtype identity ambiguous (each key maps to exactly one form set, field config, and mutation rules), so the second occurrence throws.","triggerScenarios":"A subtype list containing two entries with \"key\": \"task\" (typically after merging edits from two people or duplicating a block while adding a new subtype).","commonSituations":"Copy-paste-then-forget-to-rename when adding subtypes; merge conflicts in config resolved by keeping both sides; JSON with an entry duplicated at different positions in the list.","solutions":["Search the config for the duplicated key named in the message and delete or rename the redundant entry","When adding a subtype by duplicating an existing block, change the \"key\" first","Lint the list (unique key count == entry count) before saving"],"exampleFix":"// before\n[\n  { \"key\": \"default\", \"name\": \"Default\" },\n  { \"key\": \"task\", \"name\": \"Task\" },\n  { \"key\": \"task\", \"name\": \"Maintenance\" }\n]\n\n// after\n[\n  { \"key\": \"default\", \"name\": \"Default\" },\n  { \"key\": \"task\", \"name\": \"Task\" },\n  { \"key\": \"maintenance\", \"name\": \"Maintenance\" }\n]","handlingStrategy":"validation","validationCode":"$keys = array_column($config, 'key');\nif (count($keys) !== count(array_unique($keys))) {\n  // reject before saving: duplicate subtype keys present\n}","typeGuard":"function hasUniqueSubtypeKeys(array $config) {\n  $keys = array_column($config, 'key');\n  return count($keys) === count(array_unique($keys));\n}","tryCatchPattern":null,"preventionTips":["When duplicating a subtype block, change the key before anything else","Resolve config merge conflicts by hand and re-run a uniqueness check","Add a config lint step (shape, key rules, uniqueness, default present) to deployment"],"tags":["phabricator","subtypes","config-validation","duplicate-key","php"],"backgroundTag":"config-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}