influxdata/influxdb · critical

CA certificate PEM should be valid

Error message

CA certificate PEM should be valid

What it means

ConnectionBuilder in core/client_util attaches a custom root CA for TLS by parsing the configured PEM with reqwest::Certificate::from_pem and .expect()ing success, so a malformed PEM panics the process instead of returning an error. from_pem requires PEM-encoded X.509 CERTIFICATE blocks; it rejects DER bytes, truncated files, wrong block types (e.g. a PRIVATE KEY block), or PEM surrounded by unrelated text.

Source

Thrown at core/client_util/src/connection.rs:187

            .connect_timeout(self.connect_timeout)
            .timeout(self.timeout);
        Ok(endpoint)
    }

    fn compose_middleware(self, channel: Channel, endpoint: Endpoint) -> Connection {
        let headers_map: HeaderMap = self.headers.iter().cloned().collect();

        // Compose channel with new tower middleware stack
        let grpc_connection = tower::ServiceBuilder::new()
            .layer(SetRequestHeadersLayer::new(self.headers))
            .service(channel);

        let mut http_builder = reqwest::Client::builder()
            .connection_verbose(true)
            .default_headers(headers_map);
        if let Some(pem) = &self.ca_certificate_pem {
            let cert =
                reqwest::Certificate::from_pem(pem).expect("CA certificate PEM should be valid");
            http_builder = http_builder.add_root_certificate(cert);
        }
        let http_client = http_builder
            .build()
            .expect("reqwest::Client should have built");

        let http_connection = HttpConnection::new(endpoint.uri().clone(), http_client);

        Connection::new(grpc_connection, http_connection)
    }

    /// Set the `User-Agent` header sent by this client.
    pub fn user_agent(self, user_agent: impl Into<String>) -> Self {
        Self {
            user_agent: user_agent.into(),
            ..self
        }
    }

View on GitHub (pinned to d28e26e048)

Solutions

  1. Validate the file first: openssl x509 -in ca.pem -noout -text must succeed
  2. If the cert is DER, convert it: openssl x509 -inform der -in ca.der -out ca.pem
  3. Confirm the file contains only -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- sections and nothing else
  4. Parse defensively in your own code: call reqwest::Certificate::from_pem(...)? yourself before building the connection and propagate the error

Example fix

// before: relies on the library's expect and panics
let conn = ConnectionBuilder::new(uri).ca_certificate_pem(pem_bytes).connect();

// after: validate first, surface a real error
let cert = reqwest::Certificate::from_pem(&pem_bytes)
    .context("CA certificate file is not valid PEM")?;
let conn = ConnectionBuilder::new(uri).ca_certificate_pem(pem_bytes).connect();
Defensive patterns

Strategy: validation

Validate before calling

// validate the PEM before handing it to the connection builder
fn valid_pem(pem: &[u8]) -> bool {
    reqwest::Certificate::from_pem(pem).is_ok()
}
if let Some(pem) = &config.ca_certificate_pem {
    anyhow::ensure!(valid_pem(pem), "ca_certificate_pem is not a valid PEM certificate");
}

Try / catch

match reqwest::Certificate::from_pem(&pem_bytes) {
    Ok(cert) => builder = builder.add_root_certificate(cert),
    Err(e) => return Err(anyhow!("invalid CA PEM: {e}; run: openssl x509 -in ca.pem -noout -text")),
}

Prevention

When it happens

Trigger: Setting ca_certificate_pem from a file that is not a valid PEM certificate: a DER-encoded cert, the TLS private key, an empty file, or certificate text mangled by copy/paste (missing BEGIN/END lines, embedded quotes or whitespace).

Common situations: Self-signed or private-CA deployments where the wrong secret is mounted; scripts that download a cert and capture an error page; passing the server key instead of the CA cert.

Understand the failure class

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/c5c50f714b5200dc. Report an issue: GitHub.