jackc/pgx · error
unable to add CA to cert pool
Error message
unable to add CA to cert pool
What it means
Returned by configTLS when x509.CertPool.AppendCertsFromPEM returns false for the sslrootcert file. AppendCertsFromPEM returns false only when the PEM data contains no parseable certificates, so the file is empty, not PEM, or corrupted. The TLS config cannot be built without a valid CA, so connection setup aborts.
Source
Thrown at pgconn/config.go:856
var err error
caCertPool, err = x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("unable to load system certificate pool: %w", err)
}
sslmode = "verify-full"
} else {
caCertPool = x509.NewCertPool()
caPath := sslrootcert
caCert, err := os.ReadFile(caPath)
if err != nil {
return nil, fmt.Errorf("unable to read CA file: %w", err)
}
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, errors.New("unable to add CA to cert pool")
}
}
tlsConfig.RootCAs = caCertPool
tlsConfig.ClientCAs = caCertPool
}
switch sslmode {
case "disable":
return []*tls.Config{nil}, nil
case "allow", "prefer":
tlsConfig.InsecureSkipVerify = true
case "require":
// According to PostgreSQL documentation, if a root CA file exists,
// the behavior of sslmode=require should be the same as that of verify-ca
//
// See https://www.postgresql.org/docs/current/libpq-ssl.html
if sslrootcert != "" {View on GitHub (pinned to ec1a0befd2)
Solutions
- Ensure sslrootcert points to a PEM-encoded CA certificate bundle (BEGIN CERTIFICATE blocks).
- If you have a DER cert, convert it: 'openssl x509 -inform der -in ca.der -out ca.pem'.
- Verify the file with 'openssl x509 -in ca.pem -noout -text' before using it.
- Use sslrootcert=system to rely on the OS trust store when appropriate.
Example fix
# before: pointed at a DER file or wrong file sslrootcert=/etc/ssl/db-ca.der # after: PEM-encoded CA openssl x509 -inform der -in /etc/ssl/db-ca.der -out /etc/ssl/db-ca.pem sslrootcert=/etc/ssl/db-ca.pem
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the sslrootcert file is valid PEM with at least one cert before connecting.
func validateRootCertPEM(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(data) {
return fmt.Errorf("%s contains no PEM-encoded certificates", path)
}
return nil
} Try / catch
if _, err := pgx.ParseConfig(dsn); err != nil {
if strings.Contains(err.Error(), "unable to add CA to cert pool") {
return fmt.Errorf("sslrootcert is not valid PEM; convert DER->PEM or fix the file: %w", err)
}
} Prevention
- Store CA certs in PEM (BEGIN CERTIFICATE) form only.
- Validate the file with 'openssl x509 -in ca.pem -noout -text' during provisioning.
- Use sslrootcert=system when the OS trust store is appropriate.
When it happens
Trigger: Setting sslrootcert to a path whose contents are not valid PEM certificates (e.g. a DER-encoded cert, a private key file, random text, or an empty file). Read succeeds but AppendCertsFromPEM fails.
Common situations: Pointing sslrootcert at a .key file by mistake; downloading a cert in DER instead of PEM; cert file truncated to zero bytes; copy-paste error inserting the cert into the file.
Related errors
- no peer certificates for channel binding
- OAuth authentication required but no token provider configur
- channel binding required but server does not support SCRAM-S
- channel binding required but channel binding data is not ava
- invalid SCRAM ServerSignature received from server
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/4258dd45bc41421e.json.
Report an issue: GitHub.