{"record":{"id":"aa340be46fb212f4","repo":"phacility/phabricator","slug":"patch-s-has-unknown-patch-type-s","errorCode":null,"errorMessage":"Patch '%s' has unknown patch type '%s'.","messagePattern":"Patch '(.+?)' has unknown patch type '(.+?)'\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/storage/patch/PhabricatorSQLPatchList.php","lineNumber":209,"sourceCode":"          }\n        }\n\n        $type = idx($patch, 'type');\n        if (!$type) {\n          throw new Exception(\n            pht(\n              \"Patch '%s' is missing key '%s'. Every patch must have a type.\",\n              \"{$namespace}:{$key}\",\n              'type'));\n        }\n\n        switch ($type) {\n          case 'db':\n          case 'sql':\n          case 'php':\n            break;\n          default:\n            throw new Exception(\n              pht(\n                \"Patch '%s' has unknown patch type '%s'.\",\n                \"{$namespace}:{$key}\",\n                $type));\n        }\n\n        $specs[$full_key] = $patch;\n      }\n    }\n\n    foreach ($specs as $key => $patch) {\n      foreach ($patch['after'] as $after) {\n        if (empty($specs[$after])) {\n          throw new Exception(\n            pht(\n              \"Patch '%s' references nonexistent dependency, '%s'. \".\n              \"Patches may only depend on patches which actually exist.\",\n              $key,","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/storage/patch/PhabricatorSQLPatchList.php#L191-L227","documentation":"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.","triggerScenarios":"A patch entry sets 'type' to something outside db/sql/php: 'phps', 'PHP', 'ddl', 'migration', a filename extension like '.sql', etc.","commonSituations":"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.","solutions":["Correct 'type' to the exact lowercase literal: 'db', 'sql', or 'php'.","Double-check the entry against a working patch in the same list.","Re-run 'bin/storage status' to confirm the list loads."],"exampleFix":"// before\n'20180101.widget.php' => array(\n  'type' => 'PHP',\n  'name' => $this->getPatchPath('20180101.widget.php'),\n),\n\n// after\n'20180101.widget.php' => array(\n  'type' => 'php',\n  'name' => $this->getPatchPath('20180101.widget.php'),\n),","handlingStrategy":"type-guard","validationCode":"$known_types = array('db' => true, 'sql' => true, 'php' => true);\nforeach ((new MyApplicationPatchList())->getPatches() as $key => $patch) {\n  $type = idx($patch, 'type');\n  if (!isset($known_types[$type])) {\n    throw new Exception(\"Patch '{$key}' has invalid type '{$type}'\");\n  }\n}","typeGuard":"// PHP has no enum here; guard with a lookup of the three legal literals:\nfunction is_valid_patch_type($type) {\n  $known = array('db' => true, 'sql' => true, 'php' => true);\n  return isset($known[$type]);\n}","tryCatchPattern":null,"preventionTips":["The type is always the lowercase file verb: .sql -> 'sql', PHP script -> 'php', database creation -> 'db'.","Review patch diffs for capitalized or inventive type strings before merging."],"tags":["phabricator","database-migration","patch-type","php"],"backgroundTag":"database-migration-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}