quickwit-oss/quickwit · error

no CA certificate found in `{ca_path}`

Error message

no CA certificate found in `{ca_path}`

What it means

After loading certificates from `tls.ca_path`, load_root_cert_store verifies that at least one CA certificate was parsed. If the file exists but contains no parseable PEM certificates, it fails with this ensure! error, since an empty RootCertStore cannot verify peers.

Source

Thrown at quickwit/quickwit-transport/src/tls.rs:246

        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 poll
/// (`cert_poll_interval`) and the process-wide [`CERT_RELOAD_TX`] trigger (e.g. `SIGHUP`).
///
/// The task only holds a `Weak` reference, plus a transient strong reference while reloading. Once
/// the owner drops the config (the sole strong owner) the next `upgrade` fails and the task
/// returns.
fn spawn_cert_reload_task(resolver: Arc<ReloadableCertResolver>, cert_poll_interval: Duration) {
    let weak_resolver = Arc::downgrade(&resolver);

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Verify the file at ca_path contains PEM-formatted certificate(s) starting with -----BEGIN CERTIFICATE-----
  2. Convert DER to PEM if needed (openssl x509 -inform der -in ca.der -out ca.pem)
  3. Check that the file is non-empty and mounted correctly (not the private key)

Example fix

// before
ca_path: "/etc/quickwit/tls/server.key"   // key file, no certs
// after
ca_path: "/etc/quickwit/tls/ca.pem"       // PEM CA bundle
Defensive patterns

Strategy: validation

Validate before calling

# bash precheck
grep -q -- "-----BEGIN CERTIFICATE-----" "$CA_PATH" || { echo "$CA_PATH has no PEM certs"; exit 1; }

Prevention

When it happens

Trigger: ca_path points to a file with no PEM `-----BEGIN CERTIFICATE-----` blocks (e.g. a private key file, an empty file, or DER/binary format instead of PEM); file contains only intermediate cert chains in an unparseable format.

Common situations: Pointing ca_path at the server key file by mistake; using a DER-encoded CA instead of PEM; a mis-mounted Kubernetes secret that produced an empty or wrong file.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/b561bf9f5470197b. Report an issue: GitHub.