phacility/phabricator · error · Exception

Subtype configuration is invalid: two subtypes use the same

Error message

Subtype configuration is invalid: two subtypes use the same key ("%s"). Each subtype must have a unique key.

What it means

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.

Source

Thrown at src/applications/transactions/editengine/PhabricatorEditEngineSubtype.php:175

    foreach ($config as $value) {
      PhutilTypeSpec::checkMap(
        $value,
        array(
          'key' => 'string',
          'name' => 'string',
          'tag' => 'optional string',
          'color' => 'optional string',
          'icon' => 'optional string',
          'children' => 'optional map<string, wild>',
          'fields' => 'optional map<string, wild>',
          'mutations' => 'optional list<string>',
        ));

      $key = $value['key'];
      self::validateSubtypeKey($key);

      if (isset($map[$key])) {
        throw new Exception(
          pht(
            'Subtype configuration is invalid: two subtypes use the same '.
            'key ("%s"). Each subtype must have a unique key.',
            $key));
      }

      $map[$key] = true;

      $name = $value['name'];
      if (!strlen($name)) {
        throw new Exception(
          pht(
            'Subtype configuration is invalid: subtype with key "%s" has '.
            'no name. Subtypes must have a name.',
            $key));
      }

      $children = idx($value, 'children');

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Search the config for the duplicated key named in the message and delete or rename the redundant entry
  2. When adding a subtype by duplicating an existing block, change the "key" first
  3. Lint the list (unique key count == entry count) before saving

Example fix

// before
[
  { "key": "default", "name": "Default" },
  { "key": "task", "name": "Task" },
  { "key": "task", "name": "Maintenance" }
]

// after
[
  { "key": "default", "name": "Default" },
  { "key": "task", "name": "Task" },
  { "key": "maintenance", "name": "Maintenance" }
]
Defensive patterns

Strategy: validation

Validate before calling

$keys = array_column($config, 'key');
if (count($keys) !== count(array_unique($keys))) {
  // reject before saving: duplicate subtype keys present
}

Type guard

function hasUniqueSubtypeKeys(array $config) {
  $keys = array_column($config, 'key');
  return count($keys) === count(array_unique($keys));
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/4243e25eb90670a2. Report an issue: GitHub.