phacility/phabricator · error · Exception

Subtype configuration is invalid: it must be a list of subty

Error message

Subtype configuration is invalid: it must be a list of subtype specifications.

What it means

PhabricatorEditEngineSubtype::validateConfiguration() starts by requiring the subtype configuration value itself to be a PHP list (array of subtype specification dictionaries). This exception fires when the config is not an array at all — a string, map, or scalar — i.e. the whole shape is wrong before any individual subtype is inspected.

Source

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

      throw new Exception(
        pht(
          'Subtype "%s" is not valid: subtype keys must have a minimum '.
          'length of 3 bytes.',
          $subtype));
    }

    if (!preg_match('/^[a-z]+\z/', $subtype)) {
      throw new Exception(
        pht(
          'Subtype "%s" is not valid: subtype keys may only contain '.
          'lowercase latin letters ("a" through "z").',
          $subtype));
    }
  }

  public static function validateConfiguration($config) {
    if (!is_array($config)) {
      throw new Exception(
        pht(
          'Subtype configuration is invalid: it must be a list of subtype '.
          'specifications.'));
    }

    $map = array();
    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>',

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Make the top-level value a JSON list of dictionaries, each carrying its own "key" field
  2. Start from the documented example config (a list containing at least the "default" subtype) and extend it
  3. Re-save through the config editor and re-read the stored value to confirm it is a list

Example fix

// before
{
  "bug":     { "name": "Bug" },
  "feature": { "name": "Feature" }
}
// Exception: Subtype configuration is invalid: it must be a list ...

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

Strategy: validation

Validate before calling

if (!is_array($config) || $config !== array_values($config)) {
  // reject before saving: config must be a LIST of subtype dicts
}

Type guard

function isSubtypeConfigList($config) {
  return is_array($config)
    && $config === array_values($config)
    && array_filter($config, 'is_array') === $config;
}

Prevention

When it happens

Trigger: Setting maniphest.subtypes (or the engine's subtype config) to a JSON object keyed by subtype ({"bug": {...}}), a string, or leaving a placeholder scalar instead of a JSON list [{...}, {...}].

Common situations: Hand-editing raw config JSON and using a map because it reads nicer; pasting YAML-style mappings; misunderstanding that the container must be a list with 'key' inside each entry.

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