phacility/phabricator · error · Exception

%s '%s' has a patch with a colon in the key name, '%s'. Patc

Error message

%s '%s' has a patch with a colon in the key name, '%s'. Patch keys may not contain colons.

What it means

Patch keys may not contain ':' because Phabricator composes globally unique full keys as "namespace:key" (see the $full_key assignment right after this check). A colon inside a patch key would corrupt that namespacing and make applied-patch tracking ambiguous, so the loader rejects it immediately.

Source

Thrown at src/infrastructure/storage/patch/PhabricatorSQLPatchList.php:112

                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),
              $key));
        }

        if (strpos($key, ':') !== false) {
          throw new Exception(
            pht(
              "%s '%s' has a patch with a colon in the key name, '%s'. ".
              "Patch keys may not contain colons.",
              __CLASS__,
              get_class($patch_list),
              $key));
        }

        $namespace = $patch_list->getNamespace();
        $full_key = "{$namespace}:{$key}";

        if (isset($specs[$full_key])) {
          throw new Exception(
            pht(
              "%s '%s' has a patch '%s' which duplicates an ".
              "existing patch key.",
              __CLASS__,
              get_class($patch_list),

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Strip the namespace prefix and colon from the key, leaving only the bare patch name.
  2. Confirm getNamespace() for the class supplies the prefix automatically.
  3. Re-run 'bin/storage status' to confirm the list loads.

Example fix

// before
'phabricator:20180101.widget.sql' => array(
  'type' => 'sql',
  'name' => $this->getPatchPath('20180101.widget.sql'),
),

// after
'20180101.widget.sql' => array(
  'type' => 'sql',
  'name' => $this->getPatchPath('20180101.widget.sql'),
),
Defensive patterns

Strategy: validation

Validate before calling

// Reject colons before the storage layer does:
foreach ((new MyApplicationPatchList())->getPatches() as $key => $spec) {
  if (strpos($key, ':') !== false) {
    throw new Exception("Patch keys must not contain ':': {$key}");
  }
}

Prevention

When it happens

Trigger: A patch key in getPatches() contains a colon — e.g. copying a full key like 'phabricator:20180101.foo.sql' from storage logs or 'bin/storage status' output and pasting it as the array key in a patch list (it must be the bare '20180101.foo.sql' inside its own namespace).

Common situations: Copying a fully-qualified patch name from error output, migration logs, or the patch_status database table back into a patch definition; writing dependencies in 'after' as keys in your own list by mistake.

Related errors


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