{"record":{"id":"70f55a2054186fe9","repo":"risingwavelabs/risingwave","slug":"failed-to-parse-client-key","errorCode":null,"errorMessage":"Failed to parse client key","messagePattern":"Failed to parse client key","errorType":"exception","errorClass":"PsqlError","httpStatus":null,"severity":"error","filePath":"src/utils/pgwire/src/ldap_auth.rs","lineNumber":156,"sourceCode":"                        .into(),\n                )\n            })?;\n            let client_key_bytes = fs::read(key).map_err(|e| {\n                PsqlError::StartupError(anyhow!(e).context(\"Failed to read client key\").into())\n            })?;\n            let client_certs = CertificateDer::pem_slice_iter(&client_cert_bytes)\n                .collect::<Result<Vec<_>, _>>()\n                .map_err(|e| {\n                    PsqlError::StartupError(\n                        anyhow!(e)\n                            .context(\"Failed to parse client certificate\")\n                            .into(),\n                    )\n                })?;\n\n            let client_private_key =\n                PrivateKeyDer::from_pem_slice(&client_key_bytes).map_err(|e| {\n                    PsqlError::StartupError(anyhow!(e).context(\"Failed to parse client key\").into())\n                })?;\n\n            tls_client_config\n                .with_client_auth_cert(client_certs, client_private_key)\n                .map_err(|err| {\n                    PsqlError::StartupError(\n                        anyhow!(err)\n                            .context(\"Failed to set client certificate\")\n                            .into(),\n                    )\n                })\n        } else {\n            Ok(tls_client_config.with_no_client_auth())\n        }\n    }\n}\n\n/// LDAP configuration extracted from HBA entry","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/utils/pgwire/src/ldap_auth.rs#L138-L174","documentation":"The client key bytes were read fine but PrivateKeyDer::from_pem_slice failed to decode them as a PEM-encoded private key (RSA, PKCS8, EC, etc.). This StartupError indicates the key material is not parseable by rustls, so the client-auth TLS config cannot be built and connection establishment stops.","triggerScenarios":"PrivateKeyDer::from_pem_slice(&client_key_bytes) returns Err — key file is malformed PEM, uses an unsupported key format, or is encrypted (password-protected) PEM","commonSituations":"Key is in a format rustls rejects (e.g. traditional 'BEGIN RSA PRIVATE KEY' with exotic parameters, or PKCS#12 .pfx); key is passphrase-encrypted; file actually contains a certificate or the CSR; key truncated or CRLF-mangled on Windows.","solutions":["Convert the key to unencrypted PKCS#8: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pkcs8.pem","Decrypt an encrypted key first: openssl rsa -in encrypted.key -out decrypted.key","Confirm the file holds the private key (-----BEGIN PRIVATE KEY-----/BEGIN RSA PRIVATE KEY-----), not the cert","Ensure the key corresponds to the configured client certificate"],"exampleFix":"// before\nopenssl req -newkey rsa:2048 -nodes  # produced 'BEGIN PRIVATE KEY' with local params\n// after (normalize for rustls)\nopenssl pkcs8 -topk8 -nocrypt -in client.key -out client_pkcs8.key\n# then: client_key = '/etc/rw/certs/client_pkcs8.key'","handlingStrategy":"validation","validationCode":"fn is_parseable_key_pem(path: &str) -> bool {\n    std::fs::read_to_string(path).map(|s| {\n        [\"-----BEGIN PRIVATE KEY-----\", \"-----BEGIN RSA PRIVATE KEY-----\", \"-----BEGIN EC PRIVATE KEY-----\"]\n            .iter().any(|h| s.starts_with(h)) && !s.contains(\"ENCRYPTED\")\n    }).unwrap_or(false)\n}","typeGuard":"fn is_unencrypted_key_pem(s: &str) -> bool {\n    s.contains(\"-----BEGIN\") && s.contains(\"PRIVATE KEY-----\") && !s.contains(\"ENCRYPTED\")\n}","tryCatchPattern":"catch PsqlError::StartupError, inspect the rustls pki-types error in the anyhow chain and re-raise with an 'openssl pkcs8 -topk8 -nocrypt' hint","preventionTips":["Normalize all keys to unencrypted PKCS#8 before deployment","Never deploy passphrase-protected keys (automated processes cannot decrypt them)","Run `openssl pkey -in key.pem -noout` as a deploy-time check","Generate cert+key pairs in one step to guarantee they match"],"tags":["ldap","tls","private-key","pem","startup"],"backgroundTag":"invalid-argument-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}