risingwavelabs/risingwave · error · PsqlError

Failed to add CA certificate

Error message

Failed to add CA certificate

What it means

A CA certificate parsed successfully but rustls's `RootCertStore::add` rejected it when adding it to the trust store. rustls rejects certificates it cannot use as trust anchors (e.g. not a valid CA certificate).

Source

Thrown at src/utils/pgwire/src/ldap_auth.rs:108

    /// Initialize rustls ClientConfig based on TLS configuration
    fn init_client_config(&self) -> PsqlResult<rustls::ClientConfig> {
        let tls_client_config = rustls::ClientConfig::builder();

        let mut root_cert_store = rustls::RootCertStore::empty();
        if let Some(tls_config) = &self.ca_cert {
            let ca_cert_bytes = fs::read(tls_config).map_err(|e| {
                PsqlError::StartupError(anyhow!(e).context("Failed to read CA certificate").into())
            })?;
            for cert in CertificateDer::pem_slice_iter(&ca_cert_bytes) {
                let cert = cert.map_err(|e| {
                    PsqlError::StartupError(
                        anyhow!(e).context("Failed to parse CA certificate").into(),
                    )
                })?;
                root_cert_store.add(cert).map_err(|err| {
                    PsqlError::StartupError(
                        anyhow!(err).context("Failed to add CA certificate").into(),
                    )
                })?;
            }
        } else {
            // If ca certs is not present, load system native certs.
            for cert in
                rustls_native_certs::load_native_certs().expect("could not load platform certs")
            {
                root_cert_store.add(cert).map_err(|err| {
                    PsqlError::StartupError(
                        anyhow!(err)
                            .context("Failed to add native CA certificate")
                            .into(),
                    )
                })?;
            }
        }
        let tls_client_config = tls_client_config.with_root_certificates(root_cert_store);

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure the configured file is the CA (root/intermediate) certificate, not the client/server leaf certificate.
  2. Check the certificate has basicConstraints CA:TRUE (`openssl x509 -in ca.pem -text | grep CA:`).
  3. Re-export the correct CA certificate from your LDAP/PKI provider.
  4. Read the inner rustls error from the anyhow context for the specific rejection reason.

Example fix

// before: leaf server cert used as CA
ca_cert = "server-leaf.pem"
// after: actual CA cert
ca_cert = "corporate-root-ca.pem"
Defensive patterns

Strategy: validation

Validate before calling

// ensure the file is a CA cert before configuring
// openssl x509 -in ca.pem -noout -text | grep -A1 'Basic Constraints'
// expect: CA:TRUE

Try / catch

match err {
    PsqlError::StartupError(e) if e.to_string().contains("Failed to add CA certificate") => {
        eprintln!("certificate unusable as trust anchor: {}", e);
    }
    other => return Err(other),
}

Prevention

When it happens

Trigger: `root_cert_store.add(cert)` returns Err in `init_client_config` — the parsed certificate is not a well-formed CA cert (missing CA basicConstraints, malformed extensions) or is otherwise unusable as a root.

Common situations: Configuring a leaf/end-entity certificate instead of the CA certificate; empty or unusual certificate files; certificates with unsupported extensions for rustls.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/9701ccc9a95a9ad8. Report an issue: GitHub.