phacility/phabricator · error · Exception
%s '%s' has a patch, '%s', with an unknown property, '%s'.Pa
Error message
%s '%s' has a patch, '%s', with an unknown property, '%s'.Patches must have only valid keys: %s.
What it means
Phabricator's storage patch system validates every patch definition your PhabricatorSQLPatchList subclass returns from getPatches(). Each patch array may only contain the keys 'type', 'name', 'after', 'legacy', 'dead', and 'phase'; any other key aborts patch-list loading with this exception. The strict whitelist makes typos and stale keys fail fast instead of being silently ignored during a storage upgrade.
Source
Thrown at src/infrastructure/storage/patch/PhabricatorSQLPatchList.php:89
pht(
"%s '%s' has a patch '%s' which is not an array.",
__CLASS__,
get_class($patch_list),
$key));
}
$valid = array(
'type' => true,
'name' => true,
'after' => true,
'legacy' => true,
'dead' => true,
'phase' => true,
);
foreach ($patch as $pkey => $pval) {
if (empty($valid[$pkey])) {
throw new Exception(
pht(
"%s '%s' has a patch, '%s', with an unknown property, '%s'.".
"Patches must have only valid keys: %s.",
__CLASS__,
get_class($patch_list),
$key,
$pkey,
implode(', ', array_keys($valid))));
}
}
if (is_numeric($key)) {
throw new Exception(
pht(
"%s '%s' has a patch with a numeric key, '%s'. ".
"Patches must use string keys.",
__CLASS__,
get_class($patch_list),View on GitHub (pinned to 5720a38cfe)
Solutions
- Open the patch list class named in the message (second %s) and find the patch key named third; correct or delete the invalid property listed last.
- If the key was removed upstream (e.g. 'branch'), delete it rather than renaming it.
- Re-run 'bin/storage status' to confirm every patch list loads cleanly before upgrading.
- Keep a canonical, known-good patch entry beside your list and copy from it for new patches.
Example fix
// before (in your PhabricatorSQLPatchList subclass)
'20180101.widget.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20180101.widget.sql'),
'branch' => 'stable', // unknown property -> exception
),
// after
'20180101.widget.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20180101.widget.sql'),
), Defensive patterns
Strategy: validation
Validate before calling
// Fail in CI before any storage command touches the database: // PhabricatorSQLPatchList::buildAllPatches() loads and validates every patch // list; a bad key throws immediately. php -r "PhabricatorSQLPatchList::buildAllPatches(); echo 'patch lists OK\n';" // Equivalent: run `bin/storage status` as a CI step.
Prevention
- Copy the most recent patch entry in your list when adding a new one instead of writing one from memory.
- Run 'bin/storage status' (or the buildAllPatches() probe) in CI and after every patch addition.
- Keep patch spec keys alphabetical so a stray key is visible in review.
When it happens
Trigger: A patch entry returned by an application's getPatches() contains a key outside the whitelist — e.g. a copy-paste typo ('tyep' instead of 'type'), a historic key this version no longer accepts (like 'branch'), or a custom key such as 'path'. The exception fires the next time PhabricatorSQLPatchList::buildAllPatches() runs, i.e. on 'bin/storage status', 'bin/storage upgrade', or any storage-management workflow in the web UI.
Common situations: Copy-pasting a patch entry from an old branch, a fork, or an old Phabricator revision; upgrading Phabricator across versions where the valid key set changed; hand-writing the first patch of a new application and guessing key names.
Related errors
- %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
- Only patches in the '%s' namespace may contain '%s' keys.
- Storage patch "%s" specifies it should apply in phase "%s",
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/0d560e18fc4fb432.
Report an issue: GitHub.