{"record":{"id":"5842b8d1013f4b87","repo":"phacility/phabricator","slug":"subtype-configuration-is-invalid-subtype-with-key","errorCode":null,"errorMessage":"Subtype configuration is invalid: subtype with key \"%s\" has no name. Subtypes must have a name.","messagePattern":"Subtype configuration is invalid: subtype with key \"(.+?)\" has no name\\. Subtypes must have a name\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php","lineNumber":186,"sourceCode":"          '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');\n      if ($children) {\n        PhutilTypeSpec::checkMap(\n          $children,\n          array(\n            'subtypes' => 'optional list<string>',\n            'forms' => 'optional list<string|int>',\n          ));\n\n        $child_subtypes = idx($children, 'subtypes');\n        $child_forms = idx($children, 'forms');\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php#L168-L204","documentation":"Each subtype entry must have a non-empty \"name\" — it is the string shown in UI dropdowns, tag headers, and form selectors. validateConfiguration() throws when strlen($name) === 0 after the key checks pass.","triggerScenarios":"A subtype entry like {\"key\": \"bug\", \"name\": \"\"} — name key present but empty — or name omitted then filled with '' by a templating step.","commonSituations":"Adding a subtype in a hurry with the intent to name it later; config generators that emit empty strings for missing values; whitespace-only names trimmed to empty.","solutions":["Give every subtype a human-readable, non-empty name","If you want the display label to equal the key, still write it out: {\"key\": \"bug\", \"name\": \"Bug\"}","Lint for empty-string names before saving"],"exampleFix":"// before\n{ \"key\": \"bug\", \"name\": \"\" }\n// Exception: subtype with key \"bug\" has no name.\n\n// after\n{ \"key\": \"bug\", \"name\": \"Bug\" }","handlingStrategy":"validation","validationCode":"foreach ($config as $entry) {\n  if (!isset($entry['name']) || !strlen(trim($entry['name']))) {\n    // reject before saving: every subtype needs a non-empty name\n  }\n}","typeGuard":"function isNonEmptySubtypeName($name) {\n  return is_string($name) && strlen(trim($name)) > 0;\n}","tryCatchPattern":null,"preventionTips":["Fill in the name at creation time; never ship placeholder empty strings","Trim whitespace when importing names from spreadsheets","Lint for empty names alongside the key checks"],"tags":["phabricator","subtypes","config-validation","missing-field","php"],"backgroundTag":"config-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}