phacility/phabricator · error · Exception
Patch '%s' references nonexistent dependency, '%s'. Patches
Error message
Patch '%s' references nonexistent dependency, '%s'. Patches may only depend on patches which actually exist.
What it means
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.
Source
Thrown at src/infrastructure/storage/patch/PhabricatorSQLPatchList.php:223
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,
$after));
}
$patch_phase = $patch['phase'];
$after_phase = $specs[$after]['phase'];
if ($patch_phase !== $after_phase) {
throw new Exception(
pht(
'Storage patch "%s" executes in phase "%s", but depends on '.
'patch "%s" which is in a different phase ("%s"). Patches '.
'may not have dependencies across phases.',
$key,
$patch_phase,View on GitHub (pinned to 5720a38cfe)
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.
Example fix
// before (inside application namespace 'myapp') 'after' => array( '20171231.core.thing.sql', // actually a phabricator patch -> not found ), // after 'after' => array( 'phabricator:20171231.core.thing.sql', ),
Defensive patterns
Strategy: validation
Validate before calling
// Verify every dependency resolves in the global patch map:
$specs = PhabricatorSQLPatchList::buildAllPatches(); // itself throws on dangling refs
foreach ((new MyApplicationPatchList())->getPatches() as $key => $patch) {
foreach (idx($patch, 'after', array()) as $after) {
if (strpos($after, ':') === false) {
$after = $list->getNamespace().':'.$after; // mirror the loader's expansion
}
if (empty($specs[$after])) {
throw new Exception("Patch '{$key}' depends on missing patch '{$after}'");
}
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Patch '%s' is missing key 'after', and is the first patch in
- %s '%s' has a patch, '%s', with an unknown property, '%s'.Pa
- %s '%s' has a patch with a numeric key, '%s'. Patches must u
- %s '%s' has a patch with a colon in the key name, '%s'. Patc
- %s '%s' has a patch '%s' which duplicates an existing patch
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/6e5591893564c5df.
Report an issue: GitHub.