quickwit-oss/quickwit · error
TLS CA certificate path (`tls.ca_path`) is not set; it is re
Error message
TLS CA certificate path (`tls.ca_path`) is not set; it is required to verify peer certificates
What it means
Quickwit's TLS transport requires a CA certificate bundle to authenticate peer certificates. load_root_cert_store rejects an empty `tls.ca_path` upfront with this ensure! error because without a CA path the resulting RootCertStore could not verify anything, for both server and client TLS configs.
Source
Thrown at quickwit/quickwit-transport/src/tls.rs:239
/// its own hot-reloadable identity (`cert_path`/`key_path`) and the reload task is spawned. ALPN is
/// fixed to `h2`, which is all gRPC speaks.
pub fn make_tls_client_config(tls_config: &TlsConfig) -> anyhow::Result<Arc<ClientConfig>> {
let roots = load_root_cert_store(&tls_config.ca_path)?;
let builder = ClientConfig::builder().with_root_certificates(roots);
let mut client_config = if tls_config.verify_client_cert {
let resolver = ReloadableCertResolver::load(&tls_config.cert_path, &tls_config.key_path)?;
spawn_cert_reload_task(resolver.clone(), *tls_config.cert_poll_interval);
builder.with_client_cert_resolver(resolver)
} else {
builder.with_no_client_auth()
};
client_config.alpn_protocols = vec![b"h2".to_vec()];
Ok(Arc::new(client_config))
}
/// Loads the CA certificate(s) at `ca_path` into a [`RootCertStore`].
fn load_root_cert_store(ca_path: &str) -> anyhow::Result<RootCertStore> {
anyhow::ensure!(
!ca_path.is_empty(),
"TLS CA certificate path (`tls.ca_path`) is not set; it is required to verify peer \
certificates"
);
let ca_certs = load_certs(ca_path)
.with_context(|| format!("failed to load TLS CA certificate(s) from `{ca_path}`"))?;
anyhow::ensure!(
!ca_certs.is_empty(),
"no CA certificate found in `{ca_path}`"
);
let mut roots = RootCertStore::empty();
for ca_cert in ca_certs {
roots.add(ca_cert)?;
}
Ok(roots)
}
/// Spawns a background task that reloads `resolver`'s certificate, driven by both a periodic pollView on GitHub (pinned to a39730c5cd)
Solutions
- Set `tls.ca_path` to a file containing the CA certificate(s) in PEM format in the relevant TLS config block
- Verify the config file after templating: ca_path must be a non-empty string pointing to an existing file
- If TLS was not intended, disable the TLS setting instead of leaving ca_path empty
Example fix
# before tls: enabled: true ca_path: "" # after tls: enabled: true ca_path: "/etc/quickwit/tls/ca.crt"
Defensive patterns
Strategy: validation
Validate before calling
# Config-side precheck before deploy
tls_ca = config.get("tls", {}).get("ca_path", "")
if not tls_ca:
raise ValueError("tls.ca_path must be set when TLS is enabled") Prevention
- Always set tls.ca_path whenever any TLS option is enabled
- Validate rendered config files (Helm/env templates) for empty values before rollout
- Mount the CA bundle in all pods/nodes that run with TLS
When it happens
Trigger: Configuring TLS enabled (e.g. grpc/peering TLS settings) while leaving `tls.ca_path` empty or unset; passing an empty string from environment/template substitution into ca_path.
Common situations: Deploying a Quickwit cluster with TLS turned on but forgetting to mount/distribute the CA bundle; Helm/env templating rendering an empty ca_path value; copying a TLS config from a non-TLS setup.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- `tls.cert_poll_interval` must be greater than zero, got `{}`
- no CA certificate found in `{ca_path}`
- index ID pattern `{pattern}` is invalid: patterns must not c
- index ID pattern `{pattern}` is invalid: an index ID must ha
- index config merge policy `max_merge_factor` must be superio
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/feecae11ee96de91.
Report an issue: GitHub.