{"record":{"id":"7f7fd05ece5b3739","repo":"quickwit-oss/quickwit","slug":"the-metastore-read-replica-service-must-run-stan","errorCode":null,"errorMessage":"the `metastore_read_replica` service must run standalone and cannot be combined with any other service","messagePattern":"the `metastore_read_replica` service must run standalone and cannot be combined with any other service","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-config/src/node_config/serialize.rs","lineNumber":433,"sourceCode":"            \"the `compactor` service can only be enabled when `enable_standalone_compactors` is \\\n             true (or `QW_ENABLE_STANDALONE_COMPACTORS=true`). With the default indexer-local \\\n             merge pipeline, the compactor service must not be enabled.\"\n        );\n    }\n    validate_disk_usage(node_config);\n    Ok(())\n}\n\n/// Validates the configuration of the [`QuickwitService::MetastoreReadReplica`] role and searcher\n/// read-replica routing.\n///\n/// The [`QuickwitService::MetastoreReadReplica`] role serves the same gRPC service as a read-only\n/// metastore, so it must run standalone and requires `metastore_read_replica_uri` to connect to.\nfn validate_metastore_read_replica(node_config: &NodeConfig) -> anyhow::Result<()> {\n    let read_replica_enabled =\n        node_config.is_service_enabled(QuickwitService::MetastoreReadReplica);\n    if read_replica_enabled {\n        ensure!(\n            node_config.enabled_services.len() == 1,\n            \"the `metastore_read_replica` service must run standalone and cannot be combined with \\\n             any other service\"\n        );\n        ensure!(\n            node_config.metastore_read_replica_uri.is_some(),\n            \"the `metastore_read_replica` service requires `metastore_read_replica_uri` to be set\"\n        );\n    }\n    let searcher_uses_read_replica = node_config.is_service_enabled(QuickwitService::Searcher)\n        && node_config.searcher_config.use_metastore_read_replica;\n    // Avoid a deadlock where the searcher waits for a READY read replica, while the read\n    // replica waits for this primary metastore to become READY.\n    ensure!(\n        !(searcher_uses_read_replica && node_config.is_service_enabled(QuickwitService::Metastore)),\n        \"`searcher.use_metastore_read_replica` cannot be enabled on a node running the \\\n         `metastore` service\"\n    );","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-config/src/node_config/serialize.rs#L415-L451","documentation":"The `metastore_read_replica` role serves the same gRPC service as a read-only metastore and therefore must be the only service enabled on the node. `validate_metastore_read_replica` (called from validate) rejects any config where it is combined with other services, because co-hosted roles would conflict with the read-replica's readiness semantics.","triggerScenarios":"Enabling `metastore_read_replica` together with any other service (searcher, indexer, metastore, etc.) in the node's `services` list, then loading the node config through validate.","commonSituations":"Operators try to consolidate roles on small clusters and list metastore_read_replica alongside searcher or indexer; templates from all-in-one nodes are edited by adding the replica service.","solutions":["Run the metastore_read_replica on its own node: remove every other service from its `services` list.","If you need those other roles, deploy them on separate nodes with their own configs.","If a read-only metastore is not actually needed, remove `metastore_read_replica` from the services list entirely."],"exampleFix":"// before (quickwit.yaml)\nservices: [searcher, metastore_read_replica]\n\n// after (quickwit.yaml)\nservices: [metastore_read_replica]\n# searcher runs on a separate node","handlingStrategy":"validation","validationCode":"let enabled: &[QuickwitService] = &config.enabled_services;\nif enabled.contains(&QuickwitService::MetastoreReadReplica) {\n    assert_eq!(enabled.len(), 1, \"metastore_read_replica must run standalone\");\n}","typeGuard":"fn is_standalone_read_replica(services: &[QuickwitService]) -> bool {\n    !services.contains(&QuickwitService::MetastoreReadReplica) || services.len() == 1\n}","tryCatchPattern":"if let Err(e) = load_node_config(path) {\n    if e.to_string().contains(\"metastore_read_replica\") {\n        eprintln!(\"Split metastore_read_replica onto its own node: {e}\");\n    }\n    return Err(e);\n}","preventionTips":["Keep read-replica nodes on dedicated machine configs with only that service listed.","Never copy the all-in-one services list into a replica node config.","Run config validation on every node role in CI."],"tags":["config","validation","services","metastore"],"backgroundTag":"conflicting-config-options","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}