phacility/phabricator · error · Exception

Subtype configuration is invalid: subtype with key "%s" spec

Error message

Subtype configuration is invalid: subtype with key "%s" specifies that it can mutate into subtype "%s", but that is not a valid subtype.

What it means

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.

Source

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

    if (!isset($map[self::SUBTYPE_DEFAULT])) {
      throw new Exception(
        pht(
          'Subtype configuration is invalid: there is no subtype defined '.
          'with key "%s". This subtype is required and must be defined.',
          self::SUBTYPE_DEFAULT));
    }

    foreach ($config as $value) {
      $key = idx($value, 'key');

      $mutations = idx($value, 'mutations');
      if (!$mutations) {
        continue;
      }

      foreach ($mutations as $mutation) {
        if (!isset($map[$mutation])) {
          throw new Exception(
            pht(
              'Subtype configuration is invalid: subtype with key "%s" '.
              'specifies that it can mutate into subtype "%s", but that is '.
              'not a valid subtype.',
              $key,
              $mutation));
        }
      }
    }

  }

  public static function newSubtypeMap(array $config) {
    $map = array();

    foreach ($config as $entry) {
      $key = $entry['key'];
      $name = $entry['name'];

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. 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.
  2. If the target subtype was intentionally removed, delete it from all 'mutations' lists.
  3. Run 'bin/cache clear' after changing config so the parsed subtype map is rebuilt.
  4. Before deploying, validate the config in a scratch script by calling PhabricatorEditEngineSubtype parsing in a try/catch.

Example fix

// before (subtype config JSON)
[
  {"key": "bug", "name": "Bug", "mutations": ["defect"]},
  {"key": "feature", "name": "Feature"}
]

// after
[
  {"key": "bug", "name": "Bug", "mutations": ["feature"]},
  {"key": "feature", "name": "Feature"}
]
Defensive patterns

Strategy: validation

Validate before calling

// Validate subtype config before deploy / after edits
$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');
$keys = array_fuse(ipull($config, null, 'key'));
foreach ($config as $subtype) {
  foreach (idx($subtype, 'mutations', array()) as $target) {
    if (!isset($keys[$target])) {
      throw new Exception(
        pht('Subtype "%s" mutates to undefined key "%s".',
          $subtype['key'], $target));
    }
  }
}

Try / catch

try {
  $map = PhabricatorEditEngineSubtype::newSubtypes($engine);
} catch (Exception $ex) {
  // Surface a config error instead of a broken edit UI
  return $this->newDialog()->setTitle(pht('Invalid Subtype Config'))
    ->appendChild($ex->getMessage());
}

Prevention

When it happens

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

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

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/7d7dc3f296c11902. Report an issue: GitHub.