{"record":{"id":"fe0d22bf95e96dd1","repo":"phacility/phabricator","slug":"storage-patch-s-specifies-a-phase-attribute","errorCode":null,"errorMessage":"Storage patch \"%s\" specifies a \"@phase\" attribute with no phase value. Phase attributes must specify a value, like \"@phase default\".","messagePattern":"Storage patch \"(.+?)\" specifies a \"@phase\" attribute with no phase value\\. Phase attributes must specify a value, like \"@phase default\"\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/storage/patch/PhabricatorSQLPatchList.php","lineNumber":292,"sourceCode":"\n      // Skip over blank lines.\n      if (!strlen(trim($line))) {\n        continue;\n      }\n\n      // If this is a \"//\" comment...\n      if (preg_match('(^\\s*//)', $line)) {\n        $matches = null;\n        if (preg_match('(^\\s*//\\s*@(\\S+)(?:\\s+(.*))?\\z)', $line, $matches)) {\n          $attr_key = $matches[1];\n          $attr_value = trim(idx($matches, 2));\n\n          switch ($attr_key) {\n            case 'phase':\n              $phase_name = $attr_value;\n\n              if (!strlen($phase_name)) {\n                throw new Exception(\n                  pht(\n                    'Storage patch \"%s\" specifies a \"@phase\" attribute with '.\n                    'no phase value. Phase attributes must specify a value, '.\n                    'like \"@phase default\".',\n                    $patch_name));\n              }\n\n              if (!isset($phase_map[$phase_name])) {\n                throw new Exception(\n                  pht(\n                    'Storage patch \"%s\" specifies a \"@phase\" value (\"%s\"), '.\n                    'but this is not a recognized phase. Valid phases '.\n                    'are: %s.',\n                    $patch_name,\n                    $phase_name,\n                    implode(', ', $phase_list)));\n              }\n","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/storage/patch/PhabricatorSQLPatchList.php#L274-L310","documentation":"PHP storage patches can declare their execution phase with a header comment such as '// @phase worker'. The attribute parser (getPHPPatchAttributes) scans leading '//' lines; a '@phase' with no value after it is invalid because every phase attribute must name a phase, like '@phase default'.","triggerScenarios":"The first comment block of a .php patch file contains '// @phase' with nothing after it (or only whitespace). Parsing runs when the patch list is built, so any 'bin/storage' command hits it.","commonSituations":"Starting to add a phase annotation, saving, and forgetting to finish it; refactoring a header comment and accidentally deleting the phase name; copy-pasting a header template whose placeholder value was never filled in.","solutions":["Complete the attribute in the named patch file: '// @phase default' or '// @phase worker'.","If no phase was intended, delete the '@phase' line entirely (a plain '// ...' comment is fine).","Re-run 'bin/storage status' to confirm the file parses."],"exampleFix":"// before (top of 20180102.jobs.php)\n<?php\n// @phase\n// Creates job tables.\n\n// after\n<?php\n// @phase worker\n// Creates job tables.","handlingStrategy":"validation","validationCode":"// Lint PHP patch headers before the storage tooling parses them:\nforeach (Filesystem::listDirectory($this->getPatchDirectory()) as $file) {\n  if (!preg_match('/\\.php$/', $file)) { continue; }\n  $head = implode('', array_slice(file($dir.'/'.$file), 0, 10));\n  if (preg_match('/^\\s*\\/\\/\\s*@phase\\s*$/m', $head)) {\n    throw new Exception(\"{$file}: '@phase' attribute needs a value\");\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Finish phase annotations before saving patch files; a bare '// @phase' is a hard error.","If undecided about the phase, omit the line — absence means the default phase."],"tags":["phabricator","database-migration","phases","file-header"],"backgroundTag":"database-migration-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}