phacility/phabricator · error · Exception
Search engine configuration has an invalid service specifica
Error message
Search engine configuration has an invalid service specification (at index "%s"): %s.
What it means
Each service dictionary in `cluster.search` is type-checked with PhutilTypeSpec::checkMap against the allowed schema: `type` (required string) plus optional `hosts` (list of maps), `roles` (map), `port` (int), `protocol` (string), `path` (string), `version` (int). Any unknown key, missing `type`, or wrong value type is caught and rethrown with the index and the underlying check failure appended as the `%s` detail.
Source
Thrown at src/infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php:40
'list must be a dictionary describing a search service, but '.
'the value with index "%s" is not a dictionary.',
$index));
}
try {
PhutilTypeSpec::checkMap(
$spec,
array(
'type' => 'string',
'hosts' => 'optional list<map<string, wild>>',
'roles' => 'optional map<string, wild>',
'port' => 'optional int',
'protocol' => 'optional string',
'path' => 'optional string',
'version' => 'optional int',
));
} catch (Exception $ex) {
throw new Exception(
pht(
'Search engine configuration has an invalid service '.
'specification (at index "%s"): %s.',
$index,
$ex->getMessage()));
}
if (!array_key_exists($spec['type'], $engines)) {
throw new Exception(
pht(
'Invalid search engine type: %s. Valid types are: %s.',
$spec['type'],
implode(', ', array_keys($engines))));
}
if (isset($spec['hosts'])) {
foreach ($spec['hosts'] as $hostindex => $host) {
try {View on GitHub (pinned to 5720a38cfe)
Solutions
- Read the trailing detail in the message — PhutilTypeSpec names the exact offending key and expected type.
- Restrict each service map to type/hosts/roles/port/protocol/path/version with matching types (strings for protocol/path, ints for port/version).
- Move per-server connection details into a `hosts` entry (host/roles/port/protocol/path/version), not to the service level.
Example fix
// before
array(
'type' => 'elasticsearch',
'host' => 'es1.example.com',
'port' => '9200',
),
// after
array(
'type' => 'elasticsearch',
'hosts' => array(
array('host' => 'es1.example.com', 'port' => 9200),
),
), Defensive patterns
Strategy: validation
Validate before calling
$service_schema = array( 'type' => 'string', 'hosts' => 'optional list<map<string, wild>>', 'roles' => 'optional map<string, wild>', 'port' => 'optional int', 'protocol' => 'optional string', 'path' => 'optional string', 'version' => 'optional int', ); PhutilTypeSpec::checkMap($spec, $service_schema); // throws with the offending key
Type guard
function isSearchServiceSpec($spec) {
return is_array($spec)
&& isset($spec['type']) && is_string($spec['type'])
&& (!isset($spec['port']) || is_int($spec['port']))
&& (!isset($spec['version']) || is_int($spec['version']));
} Prevention
- Do not invent keys — if a knob is not in the schema (type/hosts/roles/port/protocol/path/version), it is silently unsupported or rejected here.
- Keep ints unquoted in config files; `'9200'` fails where 9200 passes.
- Re-run PhabricatorClusterSearchConfigType::validateValue() in a test whenever you template cluster.search programmatically.
When it happens
Trigger: Writing `'host' => ...` instead of `'hosts'`; adding an unsupported key such as `'timeout'` or `'engine'`; setting `'port' => '9200'` (string) instead of `9200` (int); omitting the required `'type'` key; giving `hosts` a map instead of a list.
Common situations: Transcribing an Elasticsearch URL into config by hand and splitting fields differently than the schema expects; carrying keys over from a different Phabricator version; following outdated documentation.
Related errors
- Search cluster configuration has an invalid host specificati
- Search cluster configuration is not valid: each entry in the
- Invalid search engine type: %s. Valid types are: %s.
- The following regex is malformed and cannot be used: %s
- Keyring configuration has an invalid key specification (at i
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/ac857d6df67d4e99.
Report an issue: GitHub.