risingwavelabs/risingwave · error · PsqlError

Failed to read client key

Error message

Failed to read client key

What it means

During LDAP-over-TLS client certificate setup, RisingWave reads the mTLS client key file configured via `client_key` and wraps any fs::read failure in a PsqlError::StartupError. This means the key file path was supplied but could not be read: the file does not exist, the path is wrong, or the process lacks read permission. Startup of the LDAP connection is aborted because client authentication cannot proceed without the key.

Source

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

            }
        }
        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 =
                PrivateKeyDer::from_pem_slice(&client_key_bytes).map_err(|e| {
                    PsqlError::StartupError(anyhow!(e).context("Failed to parse client key").into())
                })?;

            tls_client_config
                .with_client_auth_cert(client_certs, client_private_key)

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Verify the `client_key` path exists and is readable by the RisingWave process user (ls -l, check permissions)
  2. Use an absolute path in the config instead of a relative one
  3. Confirm the file is the private key matching the configured client certificate, not the certificate itself
  4. If client auth is not required, remove the client cert/key options so the no-client-auth branch is used

Example fix

// before
client_key = 'certs/client.key'   // relative path, wrong cwd
// after
client_key = '/etc/risingwave/certs/client.key'  // absolute, chmod 400 readable by rw user
Defensive patterns

Strategy: validation

Validate before calling

// before configuring LDAP mTLS
let key = std::path::Path::new(client_key_path);
if !key.is_file() {
    return Err(format!("client_key not a readable file: {}", client_key_path));
}
match std::fs::File::open(key) {
    Ok(_) => {},
    Err(e) => return Err(format!("client_key unreadable: {e}")),
}

Type guard

fn is_readable_file(p: &str) -> bool {
    std::path::Path::new(p).is_file() && std::fs::File::open(p).is_ok()
}

Try / catch

match PsqlError::StartupError chain, inspect downcast_ref::<std::io::Error>() for NotFound/PermissionDenied and emit a targeted config hint

Prevention

When it happens

Trigger: init_client_config is called from establish_connection when the LDAP config has client cert/key options set; fs::read(key) fails with io::Error (NotFound, PermissionDenied, is-a-directory, etc.)

Common situations: Typo in the `client_key` path in the CREATE CONNECTION / LDAP config; relative path resolved against a different working directory of the RisingWave process; key file deleted or renamed after config was written; file mounted with restrictive permissions the rw user cannot read.

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/f2565815d53b45ae. Report an issue: GitHub.