{"record":{"id":"6cf584eaa50f4a2a","repo":"phacility/phabricator","slug":"database-s-is-configured-as-a-replica-but-spec","errorCode":null,"errorMessage":"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.","messagePattern":"Database \"(.+?)\" 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\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"src/infrastructure/cluster/PhabricatorDatabaseRefParser.php","lineNumber":172,"sourceCode":"            $ref_key));\n      } else {\n        $ref_map[$ref_key] = $ref;\n        if ($ref->getIsMaster()) {\n          $master_keys[] = $ref_key;\n        }\n      }\n    }\n\n    foreach ($refs as $key => $ref) {\n      if ($ref->getIsMaster()) {\n        continue;\n      }\n\n      $server = $config[$key];\n\n      $partition = idx($server, 'partition');\n      if ($partition !== null) {\n        throw new Exception(\n          pht(\n            'Database \"%s\" is configured as a replica, but specifies a '.\n            '\"partition\". Only master databases may have a partition '.\n            'configuration. Replicas use the same configuration as the '.\n            'master they follow.',\n            $ref->getRefKey()));\n      }\n\n      $master_key = idx($server, 'master');\n      if ($master_key === null) {\n        if ($is_partitioned) {\n          throw new Exception(\n            pht(\n              'Database \"%s\" is configured as a replica, but does not '.\n              'specify which \"master\" it follows in configuration. Valid '.\n              'masters are: %s.',\n              $ref->getRefKey(),\n              implode(', ', $master_keys)));","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/cluster/PhabricatorDatabaseRefParser.php#L154-L190","documentation":"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.","triggerScenarios":"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).","commonSituations":"Migrating from a single master to a partitioned multi-master cluster; copy-pasting server blocks in config; restructuring topology during failover drills.","solutions":["Delete the `partition` key from the replica entry — replicas only carry host/port/user/pass/persistent/disabled plus `master`.","If the entry was meant to be a master, set `role => 'master'` and keep its `partition` definition.","After editing, verify with `bin/config get cluster.database`; parsing re-runs on the next request."],"exampleFix":"// before (cluster.database)\n'db-replica-a' => array(\n  'host' => 'replica.example.com',\n  'role' => 'replica',\n  'partition' => array('default'),\n),\n// after\n'db-replica-a' => array(\n  'host' => 'replica.example.com',\n  'role' => 'replica',\n  'master' => 'master.example.com:3306',\n),","handlingStrategy":"validation","validationCode":"// Before parsing / deploying cluster.database, pre-check shape:\nfunction assertNoReplicaPartitions(array $config) {\n  foreach ($config as $key => $server) {\n    if ($server['role'] !== 'master'\n        && array_key_exists('partition', $server)) {\n      throw new Exception(\n        'Replica '.$key.' must not define \"partition\".');\n    }\n  }\n}","typeGuard":"function isMasterEntry(array $server) {\n  return isset($server['role']) && $server['role'] === 'master';\n}","tryCatchPattern":null,"preventionTips":["Never clone a master entry when adding a replica — start from a minimal host/role/master block.","Lint cluster.database in CI with a script that replays PhabricatorDatabaseRefParser rules (replica ⇒ no partition; partitioned ⇒ replicas need master; master values must be host:port ref keys).","Document that partition config lives only on masters; replicas inherit it via their master."],"tags":["php","phabricator","config","database","replication","cluster","partition"],"backgroundTag":"database-cluster-misconfiguration","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}