t8y2/dbx · error

Neo4j CA certificate contains no valid PEM certificate

Error message

Neo4j CA certificate contains no valid PEM certificate

What it means

During TLS configuration for the Neo4j driver, the certificate file contents are parsed into the x509 root pool via AppendCertsFromPEM. This function returns false when the byte slice contains no valid PEM-encoded certificate blocks, so the configurer aborts rather than building a driver with no trust anchors. It means the CA certificate file is missing, empty, or not PEM format (e.g. DER/binary).

Source

Thrown at agents/drivers/neo4j-go/driver.go:82

	if tlsConfigurer != nil {
		configurers = append(configurers, tlsConfigurer)
	}
	return neo4j.NewDriver(uri, authToken, configurers...)
}

func neo4jTLSConfigurer(params connectParams) (func(*config.Config), error) {
	var tlsConfig *tls.Config
	if params.CACertPath != "" {
		certificate, err := os.ReadFile(params.CACertPath)
		if err != nil {
			return nil, fmt.Errorf("read Neo4j CA certificate: %w", err)
		}
		roots, err := x509.SystemCertPool()
		if err != nil || roots == nil {
			roots = x509.NewCertPool()
		}
		if !roots.AppendCertsFromPEM(certificate) {
			return nil, errors.New("Neo4j CA certificate contains no valid PEM certificate")
		}
		tlsConfig = &tls.Config{MinVersion: tls.VersionTLS12, RootCAs: roots}
	}
	var clientCertificateProvider neo4jauth.ClientCertificateProvider
	if params.ClientCertPath != "" || params.ClientKeyPath != "" {
		if params.ClientCertPath == "" || params.ClientKeyPath == "" {
			return nil, errors.New("both client certificate and client key are required")
		}
		provider, err := neo4jauth.NewStaticClientCertificateProvider(neo4jauth.ClientCertificate{
			CertFile: params.ClientCertPath,
			KeyFile:  params.ClientKeyPath,
		})
		if err != nil {
			return nil, fmt.Errorf("load Neo4j client certificate: %w", err)
		}
		clientCertificateProvider = provider
	}
	if tlsConfig == nil && clientCertificateProvider == nil {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Verify the CA file is PEM format: it must contain -----BEGIN CERTIFICATE----- blocks (run `openssl x509 -in ca.pem -text -noout`).
  2. Convert DER to PEM if needed: `openssl x509 -inform der -in cert.cer -out cert.pem`.
  3. Check the path/env var actually points to the CA cert file, not the key or another file, and that the file is non-empty.
  4. If using a chain, ensure at least the CA block is present and not truncated (full concatenated PEM chain is fine).

Example fix

// before
caCert, _ := os.ReadFile("./certs/ca.cer") // DER file -> AppendCertsFromPEM fails
// after
caCert, _ := os.ReadFile("./certs/ca.pem") // PEM-encoded CA certificate
Defensive patterns

Strategy: validation

Validate before calling

pem, err := os.ReadFile(caCertPath)
if err != nil || len(pem) == 0 {
    return fmt.Errorf("CA cert unreadable/empty: %s", caCertPath)
}
if !strings.Contains(string(pem), "-----BEGIN CERTIFICATE-----") {
    return fmt.Errorf("CA cert is not PEM: %s", caCertPath)
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pem) {
    return fmt.Errorf("CA cert contains no valid PEM block: %s", caCertPath)
}

Prevention

When it happens

Trigger: Calling openDriver with a TLS scheme (neo4j+s / bolt+s) and params.CertPath (or equivalent CA config) pointing to an empty file, a DER-encoded certificate, a private key instead of a cert, or a truncated/garbage file.

Common situations: Pointing the CA path at the wrong file (key vs cert), exporting certs in DER (.cer/.der) format from Windows, env var containing a path that resolves to an empty file in a container, copy-paste errors that drop the BEGIN/END lines.

Understand the failure class

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/3e069027306f32c6. Report an issue: GitHub.