phacility/phabricator · critical · Exception

Database "%s" is configured as a replica, but specifies a "p

Error message

Database "%s" is configured as a replica, but specifies a "partition". Only master databases may have a partition configuration. Replicas use the same configuration as the master they follow.

What it means

PhabricatorDatabaseRefParser::newRefs() turns the `cluster.database` config into master and replica refs. When a server entry has a role other than `master` (a replica) but also carries a `partition` key, the parser throws: application partitioning may only be declared on masters, because a replica automatically serves the same partition as the master it follows.

Source

Thrown at src/infrastructure/cluster/PhabricatorDatabaseRefParser.php:172

            $ref_key));
      } else {
        $ref_map[$ref_key] = $ref;
        if ($ref->getIsMaster()) {
          $master_keys[] = $ref_key;
        }
      }
    }

    foreach ($refs as $key => $ref) {
      if ($ref->getIsMaster()) {
        continue;
      }

      $server = $config[$key];

      $partition = idx($server, 'partition');
      if ($partition !== null) {
        throw new Exception(
          pht(
            'Database "%s" is configured as a replica, but specifies a '.
            '"partition". Only master databases may have a partition '.
            'configuration. Replicas use the same configuration as the '.
            'master they follow.',
            $ref->getRefKey()));
      }

      $master_key = idx($server, 'master');
      if ($master_key === null) {
        if ($is_partitioned) {
          throw new Exception(
            pht(
              'Database "%s" is configured as a replica, but does not '.
              'specify which "master" it follows in configuration. Valid '.
              'masters are: %s.',
              $ref->getRefKey(),
              implode(', ', $master_keys)));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Delete the `partition` key from the replica entry — replicas only carry host/port/user/pass/persistent/disabled plus `master`.
  2. If the entry was meant to be a master, set `role => 'master'` and keep its `partition` definition.
  3. After editing, verify with `bin/config get cluster.database`; parsing re-runs on the next request.

Example fix

// before (cluster.database)
'db-replica-a' => array(
  'host' => 'replica.example.com',
  'role' => 'replica',
  'partition' => array('default'),
),
// after
'db-replica-a' => array(
  'host' => 'replica.example.com',
  'role' => 'replica',
  'master' => 'master.example.com:3306',
),
Defensive patterns

Strategy: validation

Validate before calling

// Before parsing / deploying cluster.database, pre-check shape:
function assertNoReplicaPartitions(array $config) {
  foreach ($config as $key => $server) {
    if ($server['role'] !== 'master'
        && array_key_exists('partition', $server)) {
      throw new Exception(
        'Replica '.$key.' must not define "partition".');
    }
  }
}

Type guard

function isMasterEntry(array $server) {
  return isset($server['role']) && $server['role'] === 'master';
}

Prevention

When it happens

Trigger: A `cluster.database` entry has `role => 'replica'` while still containing a `partition => array(...)` key. Typical case: duplicating a master entry to add a read replica and forgetting to delete the `partition` block, or demoting a former master to replica by editing only `role`. The check is reached on every parse (partitioned or not).

Common situations: Migrating from a single master to a partitioned multi-master cluster; copy-pasting server blocks in config; restructuring topology during failover drills.

Related errors


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