{"record":{"id":"f22813a60f6d68a1","repo":"phacility/phabricator","slug":"configured-search-engine-type-s-is-unknown-val","errorCode":null,"errorMessage":"Configured search engine type \"%s\" is unknown. Valid engines are: %s.","messagePattern":"Configured search engine type \"(.+?)\" is unknown\\. Valid engines are: (.+?)\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"src/infrastructure/cluster/search/PhabricatorSearchService.php","lineNumber":193,"sourceCode":"    ->setUniqueMethod('getEngineIdentifier')\n    ->execute();\n  }\n\n  /**\n   * Create instances of PhabricatorSearchService based on configuration\n   * @return PhabricatorSearchService[]\n   */\n  public static function newRefs() {\n    $services = PhabricatorEnv::getEnvConfig('cluster.search');\n    $engines = self::loadAllFulltextStorageEngines();\n    $refs = array();\n\n    foreach ($services as $config) {\n\n      // Normally, we've validated configuration before we get this far, but\n      // make sure we don't fatal if we end up here with a bogus configuration.\n      if (!isset($engines[$config['type']])) {\n        throw new Exception(\n          pht(\n            'Configured search engine type \"%s\" is unknown. Valid engines '.\n            'are: %s.',\n            $config['type'],\n            implode(', ', array_keys($engines))));\n      }\n\n      $engine = clone($engines[$config['type']]);\n      $cluster = new self($engine);\n      $cluster->setConfig($config);\n      $engine->setService($cluster);\n      $refs[] = $cluster;\n    }\n\n    return $refs;\n  }\n\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/cluster/search/PhabricatorSearchService.php#L175-L211","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Config managed by external scripts that write raw values; removing an extension during an upgrade; per-environment overrides drifting out of sync between installs.","solutions":["Switch each service's `type` to an identifier from the message's valid-engines list (typically `mysql` at minimum).","Re-install/enable the extension providing the engine (e.g. PhabricatorElasticsearchExtension for `elasticsearch`) so the stored type resolves again.","Re-save `cluster.search` through the config application so normal validation runs and catches future drift."],"exampleFix":"// before: extension removed, config still references it\n'cluster.search' => array(\n  array('type' => 'elasticsearch', 'hosts' => array(...)),\n),\n// after: fall back to the built-in engine\n'cluster.search' => array(\n  array('type' => 'mysql'),\n),","handlingStrategy":"validation","validationCode":"// Before relying on cluster.search at runtime:\nforeach (PhabricatorEnv::getEnvConfig('cluster.search') as $config) {\n  PhabricatorClusterSearchConfigType::validateValue(\n    array($config));\n}","typeGuard":"function isInstalledSearchEngine($type) {\n  $engines = PhabricatorSearchService::loadAllFulltextStorageEngines();\n  return isset($engines[$type]);\n}","tryCatchPattern":null,"preventionTips":["Always save cluster.search through the config application or `bin/config set` so the config-type validation gate runs — never write raw rows.","When uninstalling an extension that provides a search engine, first revert cluster.search entries referencing its type.","After each deploy, run a smoke check that builds services (e.g. `bin/search status`) to catch env/config drift early."],"tags":["php","phabricator","config","search","cluster","extensions"],"backgroundTag":"unknown-search-engine-type","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}