{"record":{"id":"628ecebab9222b41","repo":"risingwavelabs/risingwave","slug":"bad-ssl-root-cert-error","errorCode":null,"errorMessage":"bad ssl root cert error: {}","messagePattern":"bad ssl root cert error: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/connector/src/connector_common/postgres.rs","lineNumber":636,"sourceCode":"                    tracing::warn!(error = %e.as_report(), \"SSL connector error\");\n                    MaybeMakeTlsConnector::NoTls(NoTls)\n                }\n            }\n        }\n        SslMode::Required => {\n            pg_config.ssl_mode(tokio_postgres::config::SslMode::Require);\n            let mut builder = SslConnector::builder(SslMethod::tls())?;\n            // disable certificate verification for `require`\n            builder.set_verify(SslVerifyMode::NONE);\n            MaybeMakeTlsConnector::Tls(MakeTlsConnector::new(builder.build()))\n        }\n\n        SslMode::VerifyCa | SslMode::VerifyFull => {\n            pg_config.ssl_mode(tokio_postgres::config::SslMode::Require);\n            let mut builder = SslConnector::builder(SslMethod::tls())?;\n            if let Some(ssl_root_cert) = &config.ssl_root_cert {\n                builder.set_ca_file(ssl_root_cert).map_err(|e| {\n                    anyhow!(format!(\"bad ssl root cert error: {}\", e.to_report_string()))\n                })?;\n            }\n            let mut connector = MakeTlsConnector::new(builder.build());\n            if !verify_hostname {\n                connector.set_callback(|c, _| {\n                    c.set_verify_hostname(false);\n                    Ok(())\n                });\n            }\n            MaybeMakeTlsConnector::Tls(connector)\n        }\n    };\n    #[cfg(madsim)]\n    let connector = NoTls;\n\n    let (client, connection) = pg_config.connect(connector).await?;\n\n    tokio::spawn(async move {","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/connector_common/postgres.rs#L618-L654","documentation":"When ssl_mode is verify-ca or verify-full, the connector builds an OpenSSL connector and loads the CA certificate file with `set_ca_file`. If that file cannot be read or parsed (missing path, bad permissions, not a PEM cert), it wraps the openssl error as 'bad ssl root cert error: ...'.","triggerScenarios":"Creating a tokio-postgres client (`create_pg_client` or `create_pg_client_from_properties`) with `ssl_mode = verify-ca`/`verify-full` and `ssl_root_cert` pointing to an unreadable/invalid file.","commonSituations":"Typo in the ssl_root_cert path; certificate file not mounted into the container; file is a DER/binary cert instead of PEM; file permissions deny the RisingWave process read access.","solutions":["Check that the `ssl_root_cert` path exists and is readable by the RisingWave process","Ensure the file is PEM-encoded (`openssl x509 -in cert.pem -text -noout` to verify); convert with `openssl x509 -inform der -in cert.der -out cert.pem`","Mount the CA cert into the container/pod and pass the container path","Test the cert against the server with `psql 'sslmode=verify-ca sslrootcert=<path> ...'`"],"exampleFix":"-- before\nssl_root_cert = '/etc/ssl/certs/ca-bundle.crt.bak'\n-- after (valid, readable PEM CA file)\nssl_root_cert = '/etc/ssl/certs/rds-ca.pem'","handlingStrategy":"validation","validationCode":"use std::os::unix::fs::PermissionsExt;\nfn check_ca_cert(path: &str) -> Result<(), String> {\n    let meta = std::fs::metadata(path).map_err(|e| format!(\"ca cert unreadable: {e}\"))?;\n    if meta.permissions().mode() & 0o444 == 0 { return Err(\"ca cert not readable\".into()); }\n    // quick PEM sniff\n    let head = std::fs::read_to_string(path).map_err(|e| format!(\"ca cert read: {e}\"))?;\n    if !head.contains(\"BEGIN CERTIFICATE\") { return Err(\"ca cert is not PEM\".into()); }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match create_pg_client_from_properties(&props) {\n    Err(e) if e.to_string().contains(\"bad ssl root cert\") => {\n        log::error!(\"CA cert misconfigured: {e}; check ssl_root_cert path/PEM encoding\");\n        Err(TlsConfigError::from(e))\n    }\n    other => other,\n}","preventionTips":["Always ship PEM-encoded CA certs and verify with `openssl x509`","Mount certs at stable container paths and reference those paths in config","Test the TLS config with `psql sslmode=verify-ca sslrootcert=...` before deploying"],"tags":["postgres","tls","ssl","certificate"],"backgroundTag":"file-not-found","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"}