{"record":{"id":"e24bef512f4d3e32","repo":"phacility/phabricator","slug":"s-s-has-a-patch-s-which-is-not-an-array","errorCode":null,"errorMessage":"%s '%s' has a patch '%s' which is not an array.","messagePattern":"(.+?) '(.+?)' has a patch '(.+?)' which is not an array\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/storage/patch/PhabricatorSQLPatchList.php","lineNumber":70,"sourceCode":"      ->setUniqueMethod('getNamespace')\n      ->execute();\n\n    $specs = array();\n    $seen_namespaces = array();\n\n    $phases = PhabricatorStoragePatch::getPhaseList();\n    $phases = array_fuse($phases);\n\n    $default_phase = PhabricatorStoragePatch::getDefaultPhase();\n\n    foreach ($patch_lists as $patch_list) {\n      $last_keys = array_fill_keys(\n        array_keys($phases),\n        null);\n\n      foreach ($patch_list->getPatches() as $key => $patch) {\n        if (!is_array($patch)) {\n          throw new Exception(\n            pht(\n              \"%s '%s' has a patch '%s' which is not an array.\",\n              __CLASS__,\n              get_class($patch_list),\n              $key));\n        }\n\n        $valid = array(\n          'type'    => true,\n          'name'    => true,\n          'after'   => true,\n          'legacy'  => true,\n          'dead'    => true,\n          'phase' => true,\n        );\n\n        foreach ($patch as $pkey => $pval) {\n          if (empty($valid[$pkey])) {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/storage/patch/PhabricatorSQLPatchList.php#L52-L88","documentation":"While merging all patch lists, a key in some PhabricatorSQLPatchList subclass's getPatches() maps to a non-array value. Every patch definition must be an array with at least `type` and `name` keys; this exception means a patch was defined as a scalar, so the patch list code itself is broken — almost always by hand editing or a bad merge.","triggerScenarios":"A getPatches() entry like 'my.change' => 'my_change.sql' (a plain string) instead of an array; the exception names the offending class and key.","commonSituations":"Writing a first custom patch and returning a filename string; merge conflicts in patch list files resolved incorrectly; copying an outdated patch-definition format from old documentation.","solutions":["Open the class named in the message and turn the flagged value into an array with `type` and `name` keys.","Copy the exact structure of neighbouring patches in the same file (valid types are db, sql, php).","Run `php -l` on the file and check for merge-conflict residue if it was recently merged."],"exampleFix":"// before\n'my.change' => 'my_change.sql',\n\n// after\n'my.change' => array(\n  'type' => 'sql',\n  'name' => 'my_change.sql',\n),","handlingStrategy":"validation","validationCode":"foreach ($patch_list->getPatches() as $key => $patch) {\n  if (!is_array($patch)) {\n    throw new InvalidArgumentException('patch '.$key.' must be an array');\n  }\n}","typeGuard":"function isPatchDefinition($patch) {\n  return is_array($patch) && isset($patch['type'], $patch['name']);\n}","tryCatchPattern":null,"preventionTips":["Model new patches on neighbouring entries in the same patch list file.","Lint patch list files (php -l plus the array check) in CI before deploy.","After resolving merge conflicts in patch files, run ./bin/storage status to confirm the map builds."],"tags":["phabricator","bin-storage","patch","patch-definition","validation"],"backgroundTag":"invalid-patch-definition","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}