phacility/phabricator · critical · Exception

Configured search engine type "%s" is unknown. Valid engines

Error message

Configured search engine type "%s" is unknown. Valid engines are: %s.

What it means

PhabricatorSearchService::newRefs() instantiates services from `cluster.search` and looks up each `type` among engines found via PhutilClassMapQuery. Config is normally validated on save, so this throw means the stored value bypassed validation or the environment changed after saving — the engine that provided the identifier (e.g. the Elasticsearch extension) is no longer loaded.

Source

Thrown at src/infrastructure/cluster/search/PhabricatorSearchService.php:193

    ->setUniqueMethod('getEngineIdentifier')
    ->execute();
  }

  /**
   * Create instances of PhabricatorSearchService based on configuration
   * @return PhabricatorSearchService[]
   */
  public static function newRefs() {
    $services = PhabricatorEnv::getEnvConfig('cluster.search');
    $engines = self::loadAllFulltextStorageEngines();
    $refs = array();

    foreach ($services as $config) {

      // Normally, we've validated configuration before we get this far, but
      // make sure we don't fatal if we end up here with a bogus configuration.
      if (!isset($engines[$config['type']])) {
        throw new Exception(
          pht(
            'Configured search engine type "%s" is unknown. Valid engines '.
            'are: %s.',
            $config['type'],
            implode(', ', array_keys($engines))));
      }

      $engine = clone($engines[$config['type']]);
      $cluster = new self($engine);
      $cluster->setConfig($config);
      $engine->setService($cluster);
      $refs[] = $cluster;
    }

    return $refs;
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Switch each service's `type` to an identifier from the message's valid-engines list (typically `mysql` at minimum).
  2. Re-install/enable the extension providing the engine (e.g. PhabricatorElasticsearchExtension for `elasticsearch`) so the stored type resolves again.
  3. Re-save `cluster.search` through the config application so normal validation runs and catches future drift.

Example fix

// before: extension removed, config still references it
'cluster.search' => array(
  array('type' => 'elasticsearch', 'hosts' => array(...)),
),
// after: fall back to the built-in engine
'cluster.search' => array(
  array('type' => 'mysql'),
),
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on cluster.search at runtime:
foreach (PhabricatorEnv::getEnvConfig('cluster.search') as $config) {
  PhabricatorClusterSearchConfigType::validateValue(
    array($config));
}

Type guard

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

Prevention

When it happens

Trigger: `cluster.search` was written directly to the database or via an env/config override that skips PhabricatorClusterSearchConfigType validation; the extension providing the configured engine was disabled or uninstalled after the config was saved; a config file from another install was deployed. getAllServices() is request-cached, so the throw recurs on every request that touches search or indexing.

Common situations: Config managed by external scripts that write raw values; removing an extension during an upgrade; per-environment overrides drifting out of sync between installs.

Related errors


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