{"record":{"id":"0b9b63d95119560e","repo":"risingwavelabs/risingwave","slug":"failed-to-parse-client-certificate","errorCode":null,"errorMessage":"Failed to parse client certificate","messagePattern":"Failed to parse client certificate","errorType":"exception","errorClass":"PsqlError","httpStatus":null,"severity":"error","filePath":"src/utils/pgwire/src/ldap_auth.rs","lineNumber":148,"sourceCode":"                return Err(PsqlError::StartupError(\n                    \"Client certificate provided without private key\".into(),\n                ));\n            };\n            let client_cert_bytes = fs::read(cert).map_err(|e| {\n                PsqlError::StartupError(\n                    anyhow!(e)\n                        .context(\"Failed to read client certificate\")\n                        .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                    )","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/utils/pgwire/src/ldap_auth.rs#L130-L166","documentation":"After successfully reading the client certificate bytes, init_client_config parses them with CertificateDer::pem_slice_iter. If any PEM block in the file is not a valid certificate (bad base64, wrong PEM label, garbage, or a non-PEM file), the iterator yields Err and this StartupError is raised. The library aborts because a usable client certificate is required for the TLS client-auth handshake.","triggerScenarios":"CertificateDer::pem_slice_iter(&client_cert_bytes).collect::<Result<Vec<_>,_>>() returns Err — the file at `client_cert` contains malformed PEM or non-certificate PEM blocks","commonSituations":"Pointing `client_cert` at the private key file or at a combined bundle that includes a key/cSR; certificate file truncated during copy/paste; file contains DER (binary) instead of PEM; extra text before/after the BEGIN/END CERTIFICATE block.","solutions":["Check the file starts with -----BEGIN CERTIFICATE----- and ends with -----END CERTIFICATE-----","Verify you are not pointing at the private key or CSR; use the issued client certificate","Convert DER to PEM if needed: openssl x509 -inform der -in cert.der -out cert.pem","Re-export the certificate cleanly (openssl x509 -in cert.pem -out clean.pem) to strip stray whitespace"],"exampleFix":"// before (config points at key file)\nclient_cert = '/etc/rw/certs/client.key'\n// after\nclient_cert = '/etc/rw/certs/client.crt'  // PEM-encoded certificate","handlingStrategy":"validation","validationCode":"fn is_pem_certificate(path: &str) -> bool {\n    std::fs::read_to_string(path).map(|s| {\n        s.contains(\"-----BEGIN CERTIFICATE-----\") && s.contains(\"-----END CERTIFICATE-----\")\n    }).unwrap_or(false)\n}\n// stronger check: openssl x509 -in cert.pem -noout >/dev/null","typeGuard":"fn looks_like_cert_pem(bytes: &[u8]) -> bool {\n    let s = String::from_utf8_lossy(bytes);\n    s.contains(\"-----BEGIN CERTIFICATE-----\")\n}","tryCatchPattern":"catch PsqlError::StartupError, downcast the inner anyhow chain to the rustls pki error and advise re-exporting the cert as PEM","preventionTips":["Distribute certs in PEM format only; never DER for this config","Keep cert and key in separate files and label filenames clearly (.crt vs .key)","Verify with `openssl x509 -in cert.pem -noout` during deploy","Avoid hand-editing PEM files; always copy whole files"],"tags":["ldap","tls","certificate","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"}