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

  1. 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.
  2. If the key was removed upstream (e.g. 'branch'), delete it rather than renaming it.
  3. Re-run 'bin/storage status' to confirm every patch list loads cleanly before upgrading.
  4. 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

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


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/0d560e18fc4fb432. Report an issue: GitHub.