risingwavelabs/risingwave · error · PsqlError

Failed to read client certificate

Error message

Failed to read client certificate

What it means

During LDAP auth TLS setup with mutual (client) certificates, the configured client certificate file could not be read from disk. The IO error is wrapped with anyhow context "Failed to read client certificate" inside a PsqlError::StartupError.

Source

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

                    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);

        if let Some(cert) = &self.cert {
            let Some(key) = &self.key else {
                return Err(PsqlError::StartupError(
                    "Client certificate provided without private key".into(),
                ));
            };
            let client_cert_bytes = fs::read(cert).map_err(|e| {
                PsqlError::StartupError(
                    anyhow!(e)
                        .context("Failed to read client certificate")
                        .into(),
                )
            })?;
            let client_key_bytes = fs::read(key).map_err(|e| {
                PsqlError::StartupError(anyhow!(e).context("Failed to read client key").into())
            })?;
            let client_certs = CertificateDer::pem_slice_iter(&client_cert_bytes)
                .collect::<Result<Vec<_>, _>>()
                .map_err(|e| {
                    PsqlError::StartupError(
                        anyhow!(e)
                            .context("Failed to parse client certificate")
                            .into(),
                    )
                })?;

            let client_private_key =

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Verify the client certificate path exists and is a readable file.
  2. Fix permissions (chown/chmod) so the risingwave process can read the file.
  3. In containers/Kubernetes, mount the client certificate secret at the configured path.
  4. If mutual TLS is not required, remove the client certificate configuration.

Example fix

// before
client_cert = "/secrets/ldap-client.crt"  // not mounted
// after: mount secret first
client_cert = "/etc/risingwave/certs/ldap-client.crt"
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
fn client_cert_readable(cert: &str, key: &str) -> Result<(), String> {
    for p in [cert, key] {
        let path = Path::new(p);
        if !path.is_file() { return Err(format!("missing file: {}", p)); }
        std::fs::File::open(path).map_err(|e| format!("{}: {}", p, e))?;
    }
    Ok(())
}

Try / catch

match err {
    PsqlError::StartupError(e) if e.to_string().contains("Failed to read client certificate") => {
        eprintln!("check client cert path/permissions/mounts: {}", e);
    }
    other => return Err(other),
}

Prevention

When it happens

Trigger: `init_client_config` calls `fs::read(cert)` on the configured client certificate path (after verifying the private key is also provided) and the read fails — path missing, unreadable, or a directory.

Common situations: Client cert path typo in LDAP connection settings; secret/cert not mounted in the container; permissions preventing the risingwave process from reading the cert file.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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