cloudflare/cloudflared · error
parse CA certificate %s
Error message
parse CA certificate %s
What it means
After successfully reading the CA file, CreateTunnelConfig feeds the PEM bytes to x509.CertPool.AppendCertsFromPEM. That function returns false when the bytes contain no parseable PEM certificate blocks (it does not return an error). Cloudflared surfaces this as "parse CA certificate <path>" to indicate the file was readable but its content is not a valid PEM-encoded certificate (or is an empty/garbage file).
Source
Thrown at tlsconfig/origin_ca.go:86
}
if !certPool.AppendCertsFromPEM(customOriginCA) {
return nil, fmt.Errorf("error appending custom CA to cert pool")
}
return certPool, nil
}
func CreateTunnelConfig(caCert string, serverName string) (*tls.Config, error) {
tlsConfig := &tls.Config{ServerName: serverName}
if caCert != "" {
caCertPEM, err := os.ReadFile(caCert) //nolint:gosec
if err != nil {
return nil, fmt.Errorf("read CA certificate %s: %w", caCert, err)
}
rootCAPool := x509.NewCertPool()
if !rootCAPool.AppendCertsFromPEM(caCertPEM) {
return nil, fmt.Errorf("parse CA certificate %s", caCert)
}
tlsConfig.RootCAs = rootCAPool
}
if tlsConfig.RootCAs == nil {
rootCAPool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.Wrap(err, "unable to get x509 system cert pool")
}
cfRootCA, err := GetCloudflareRootCA()
if err != nil {
return nil, errors.Wrap(err, "could not append Cloudflare Root CAs to cloudflared certificate pool")
}
for _, cert := range cfRootCA {
rootCAPool.AddCert(cert)
}
tlsConfig.RootCAs = rootCAPool
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Inspect the file: it must contain blocks like `-----BEGIN CERTIFICATE-----`. Run `openssl x509 -in <path> -text -noout` to validate.
- Convert DER to PEM if needed: `openssl x509 -inform der -in cert.der -out cert.pem`.
- Verify you are pointing at the CA/roots bundle, not a private key or leaf certificate chain without CERTIFICATE PEM blocks.
- Re-download or re-export the CA bundle in PEM format, or omit caCert to use the system pool plus Cloudflare roots.
Example fix
// before: file contains DER, AppendCertsFromPEM fails
// $ openssl x509 -inform der -in origin-ca.der -out origin-ca.pem
tlsCfg, err := tlsconfig.CreateTunnelConfig("/etc/cloudflared/origin-ca.pem", "example.com") Defensive patterns
Strategy: validation
Validate before calling
func isPEMCertFile(path string) error {
b, err := os.ReadFile(path)
if err != nil {
return err
}
if !bytes.Contains(b, []byte("-----BEGIN CERTIFICATE-----")) {
return fmt.Errorf("%s has no PEM CERTIFICATE blocks", path)
}
return nil
} Try / catch
tlsCfg, err := tlsconfig.CreateTunnelConfig(caPath, serverName)
if err != nil {
if strings.HasPrefix(err.Error(), "parse CA certificate") {
log.Fatal().Msgf("%s is not a PEM certificate; convert with openssl x509 -inform der", caPath)
}
log.Fatal().Err(err).Msg("failed to build tunnel TLS config")
} Prevention
- Validate CA bundles with `openssl x509 -in <file> -text -noout` before deployment.
- Always export certificates in PEM format, never DER.
- Check downloaded files are not HTML error pages (common with curl on wrong URLs).
- Point the CA flag at a root/CA bundle, not a private key or CSR.
When it happens
Trigger: CreateTunnelConfig called with a caCert path whose contents are not PEM certificates: the file holds a DER/ binary certificate, a private key, a CSR, concatenated junk, an empty file, or PEM blocks of a non-CERTIFICATE type.
Common situations: Users download a certificate in DER format instead of PEM; they point the flag at a private key or the certificate chain of the wrong entity; the file was truncated by a failed download or contains only an intermediate without any CERTIFICATE blocks; editors saved the file with HTML error-page content.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- error appending custom CA to cert pool
- read CA certificate %s: %w
- pem encoding failed: %v
- cannot decode empty certificate
- found multiple tokens in the certificate
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/c29e274d31018cc7.
Report an issue: GitHub.