phacility/phabricator · error · Exception

Invalid search engine type: %s. Valid types are: %s.

Error message

Invalid search engine type: %s. Valid types are: %s.

What it means

The service's `type` value does not match any installed fulltext storage engine identifier. Engines are collected with PhutilClassMapQuery over PhabricatorFulltextStorageEngine subclasses — `mysql` is built in, and `elasticsearch` exists only when the PhabricatorElasticsearchExtension is present. The message lists the identifiers actually available in this install.

Source

Thrown at src/infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php:49

            '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 {
            PhutilTypeSpec::checkMap(
              $host,
              array(
                'host'     => 'string',
                'roles'     => 'optional map<string, wild>',
                'port'      => 'optional int',
                'protocol'  => 'optional string',
                'path'      => 'optional string',
                'version'   => 'optional int',

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use an identifier from the 'Valid types are' list in the error, exactly as printed.
  2. For Elasticsearch, install/enable PhabricatorElasticsearchExtension first, then set `type => 'elasticsearch'`.
  3. If no extension is intended, use the built-in `type => 'mysql'`.

Example fix

// before
array('type' => 'Elasticsearch'),
// after (extension enabled)
array('type' => 'elasticsearch'),
Defensive patterns

Strategy: validation

Validate before calling

$valid = array_keys(
  PhabricatorSearchService::loadAllFulltextStorageEngines());
if (!in_array($spec['type'], $valid, true)) {
  throw new Exception(
    'Engine "'.$spec['type'].'" not installed. Valid: '.implode(', ', $valid));
}

Type guard

function isInstalledSearchEngine($type) {
  $engines = PhabricatorSearchService::loadAllFulltextStorageEngines();
  return isset($engines[$type]);
}

Prevention

When it happens

Trigger: Setting `'type' => 'Elasticsearch'` or `'elastic'` (identifiers are case-sensitive), or setting `'elasticsearch'` without the Elasticsearch extension installed/enabled. The check runs at config-save time via PhabricatorClusterSearchConfigType::validateValue.

Common situations: Configuring search before installing the extension that provides the engine; engine identifiers renamed across Phabricator versions; copying config snippets from blog posts with different casing.

Related errors


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