phacility/phabricator · critical · Exception
Database "%s" is configured as a replica, but there is no ma
Error message
Database "%s" is configured as a replica, but there is no master configured.
What it means
A replica is configured, but no entry in `cluster.database` has `role => 'master'`, so `$master_keys` is empty and there is nothing for the replica to follow. The parser only falls back to implicit selection when at least one master exists; with zero masters it throws immediately.
Source
Thrown at src/infrastructure/cluster/PhabricatorDatabaseRefParser.php:194
'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)));
} else if ($master_keys) {
$master_key = head($master_keys);
} else {
throw new Exception(
pht(
'Database "%s" is configured as a replica, but there is no '.
'master configured.',
$ref->getRefKey()));
}
}
if (!isset($ref_map[$master_key])) {
throw new Exception(
pht(
'Database "%s" is configured as a replica and specifies a '.
'master ("%s"), but that master is not a valid master. Valid '.
'masters are: %s.',
$ref->getRefKey(),
$master_key,
implode(', ', $master_keys)));
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Set the intended master entry's role to exactly `role => 'master'` (lowercase).
- If there is genuinely no local master (this install only mirrors a remote one), remove the cluster.database replica config entirely — a stand-alone install uses the standard mysql.* settings.
- Verify with `bin/config get cluster.database` that at least one entry reads `role => 'master'`.
Example fix
// before 'db-primary' => array( 'host' => 'db1.example.com', 'role' => 'primary', ), // after 'db-primary' => array( 'host' => 'db1.example.com', 'role' => 'master', ),
Defensive patterns
Strategy: validation
Validate before calling
function assertAtLeastOneMaster(array $config) {
$masters = array();
foreach ($config as $key => $server) {
if (idx($server, 'role') === 'master') { $masters[] = $key; }
}
if (!$masters) {
throw new Exception(
'cluster.database needs at least one entry with role => "master".');
}
return $masters;
} Type guard
function isMasterEntry(array $server) {
return isset($server['role']) && $server['role'] === 'master';
} Prevention
- Pin the literal 'master' string in a shared constant or template instead of free-typing roles.
- Validate role values against ['master', 'replica'] in a config lint step.
- Note that `disabled => true` does not remove a master from the candidate list — only the role string matters.
When it happens
Trigger: Every entry in `cluster.database` has a role that is not exactly the lowercase string `'master'` — e.g. `'Master'`, `'primary'`, or `'slave'` — while at least one entry is a replica. Note the `disabled` flag does not remove a master from this list, so the cause is almost always the role value itself.
Common situations: Hand-editing config and typoing the role; renaming terminology to primary/replica in config files; accidentally deleting or commenting out the master entry during cleanup.
Related errors
- Database "%s" is configured as a replica, but specifies a "p
- Database "%s" is configured as a replica, but does not speci
- Database "%s" is configured as a replica and specifies a mas
- Configured search engine type "%s" is unknown. Valid engines
- Unrecognized verb: %s
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/f180dac28e7105c2.
Report an issue: GitHub.