{"record":{"id":"6e5591893564c5df","repo":"phacility/phabricator","slug":"patch-s-references-nonexistent-dependency-s","errorCode":null,"errorMessage":"Patch '%s' references nonexistent dependency, '%s'. Patches may only depend on patches which actually exist.","messagePattern":"Patch '(.+?)' references nonexistent dependency, '(.+?)'\\. Patches may only depend on patches which actually exist\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/storage/patch/PhabricatorSQLPatchList.php","lineNumber":223,"sourceCode":"          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,\n              $after));\n        }\n\n        $patch_phase = $patch['phase'];\n        $after_phase = $specs[$after]['phase'];\n\n        if ($patch_phase !== $after_phase) {\n          throw new Exception(\n            pht(\n              'Storage patch \"%s\" executes in phase \"%s\", but depends on '.\n              'patch \"%s\" which is in a different phase (\"%s\"). Patches '.\n              'may not have dependencies across phases.',\n              $key,\n              $patch_phase,","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/storage/patch/PhabricatorSQLPatchList.php#L205-L241","documentation":"After all lists are loaded, every entry in a patch's 'after' array is looked up in the global spec map. Dependencies must reference patches that actually exist (in the same or another namespace), because Phabricator applies patches in dependency order and a dangling reference makes the order undefined. Bare dependency names are auto-prefixed with the current namespace before lookup, so a bare name of a patch from another namespace will not resolve.","triggerScenarios":"An 'after' entry is a typo ('20170101.widget.sq1'), references a patch that was renamed or removed, or names a patch from a different namespace without the 'namespace:' prefix (the loader prepends your own namespace, so it misses).","commonSituations":"Typos in dependency keys; depending on a patch that exists only in a newer/older Phabricator version than you run; depending on an extension's patch that is not installed; renaming a patch without updating its dependents.","solutions":["Check the dependency name character-by-character against the real patch key.","If the dependency lives in another namespace, spell it fully as 'namespace:patchname'.","If the dependency no longer exists (renamed/removed), update the 'after' entry to its replacement or drop it.","Re-run 'bin/storage status' to confirm all references resolve."],"exampleFix":"// before (inside application namespace 'myapp')\n'after' => array(\n  '20171231.core.thing.sql',   // actually a phabricator patch -> not found\n),\n\n// after\n'after' => array(\n  'phabricator:20171231.core.thing.sql',\n),","handlingStrategy":"validation","validationCode":"// Verify every dependency resolves in the global patch map:\n$specs = PhabricatorSQLPatchList::buildAllPatches(); // itself throws on dangling refs\nforeach ((new MyApplicationPatchList())->getPatches() as $key => $patch) {\n  foreach (idx($patch, 'after', array()) as $after) {\n    if (strpos($after, ':') === false) {\n      $after = $list->getNamespace().':'.$after; // mirror the loader's expansion\n    }\n    if (empty($specs[$after])) {\n      throw new Exception(\"Patch '{$key}' depends on missing patch '{$after}'\");\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Cross-namespace dependencies must be spelled 'namespace:patchname'; same-namespace ones may stay bare.","If you rename or delete a patch, grep every patch list for references to its old key.","Run 'bin/storage status' in CI so dangling references surface before deploy."],"tags":["phabricator","database-migration","dependencies","php"],"backgroundTag":"database-migration-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}