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
- Verify the `client_key` path exists and is readable by the RisingWave process user (ls -l, check permissions)
- Use an absolute path in the config instead of a relative one
- Confirm the file is the private key matching the configured client certificate, not the certificate itself
- 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
- Always use absolute paths for cert/key files in deployment configs
- Set key file perms to 0400 owned by the RisingWave user
- Smoke-test file readability in the deployment/init script before starting the server
- Mount certs via secrets manager with explicit path checks in readiness probes
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
- Failed to set client certificate
- Failed to read CA certificate
- Failed to read client certificate
- Failed to parse client certificate
- Failed to parse client key
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/f2565815d53b45ae.
Report an issue: GitHub.