phacility/phabricator · error · Exception

Patch '%s' has unknown patch type '%s'.

Error message

Patch '%s' has unknown patch type '%s'.

What it means

The patch 'type' key accepts exactly three values — 'db', 'sql', and 'php' — and the loader hard-verifies this with a switch whose default case throws. Any other string is a typo or an invented mechanism.

Source

Thrown at src/infrastructure/storage/patch/PhabricatorSQLPatchList.php:209

          }
        }

        $type = idx($patch, 'type');
        if (!$type) {
          throw new Exception(
            pht(
              "Patch '%s' is missing key '%s'. Every patch must have a type.",
              "{$namespace}:{$key}",
              'type'));
        }

        switch ($type) {
          case 'db':
          case 'sql':
          case 'php':
            break;
          default:
            throw new Exception(
              pht(
                "Patch '%s' has unknown patch type '%s'.",
                "{$namespace}:{$key}",
                $type));
        }

        $specs[$full_key] = $patch;
      }
    }

    foreach ($specs as $key => $patch) {
      foreach ($patch['after'] as $after) {
        if (empty($specs[$after])) {
          throw new Exception(
            pht(
              "Patch '%s' references nonexistent dependency, '%s'. ".
              "Patches may only depend on patches which actually exist.",
              $key,

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Correct 'type' to the exact lowercase literal: 'db', 'sql', or 'php'.
  2. Double-check the entry against a working patch in the same list.
  3. Re-run 'bin/storage status' to confirm the list loads.

Example fix

// before
'20180101.widget.php' => array(
  'type' => 'PHP',
  'name' => $this->getPatchPath('20180101.widget.php'),
),

// after
'20180101.widget.php' => array(
  'type' => 'php',
  'name' => $this->getPatchPath('20180101.widget.php'),
),
Defensive patterns

Strategy: type-guard

Validate before calling

$known_types = array('db' => true, 'sql' => true, 'php' => true);
foreach ((new MyApplicationPatchList())->getPatches() as $key => $patch) {
  $type = idx($patch, 'type');
  if (!isset($known_types[$type])) {
    throw new Exception("Patch '{$key}' has invalid type '{$type}'");
  }
}

Type guard

// PHP has no enum here; guard with a lookup of the three legal literals:
function is_valid_patch_type($type) {
  $known = array('db' => true, 'sql' => true, 'php' => true);
  return isset($known[$type]);
}

Prevention

When it happens

Trigger: A patch entry sets 'type' to something outside db/sql/php: 'phps', 'PHP', 'ddl', 'migration', a filename extension like '.sql', etc.

Common situations: Typos; using an uppercase variant ('SQL'); putting the file extension in 'type' instead of in the key/name; porting patch syntax from another framework (Laravel/Doctrine) where type names differ.

Related errors


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