caddyserver/caddy · error
parsing certificate: %v
Error message
parsing certificate: %v
What it means
While configuring TLS client verification, Caddy decodes each base64 DER cert in ClientAuthentication.TrustedLeafCerts (the deprecated trusted_leaf_certs option); if decodeBase64DERCert fails (bad base64 or non-X.509 DER bytes) this error wraps it. The field is deprecated — the log also emits a warning pointing you to leaf verifier modules.
Source
Thrown at modules/caddytls/connpolicy.go:880
} else {
cfg.ClientAuth = tls.RequireAnyClientCert
}
}
// enforce CA verification by adding CA certs to the ClientCAs pool
if clientauth.ca != nil {
cfg.ClientCAs = clientauth.ca.CertPool()
}
// TODO: DEPRECATED: Only here for backwards compatibility.
// If leaf cert is specified, enforce by adding a client auth module
if len(clientauth.TrustedLeafCerts) > 0 {
caddy.Log().Named("tls.connection_policy").Warn("trusted_leaf_certs is deprecated; use leaf verifier module instead")
var trustedLeafCerts []*x509.Certificate
for _, clientCertString := range clientauth.TrustedLeafCerts {
clientCert, err := decodeBase64DERCert(clientCertString)
if err != nil {
return fmt.Errorf("parsing certificate: %v", err)
}
trustedLeafCerts = append(trustedLeafCerts, clientCert)
}
clientauth.verifiers = append(clientauth.verifiers, LeafCertClientAuth{trustedLeafCerts: trustedLeafCerts})
}
// if a custom verification function already exists, wrap it
clientauth.existingVerifyPeerCert = cfg.VerifyPeerCertificate
cfg.VerifyConnection = clientauth.verifyConnection
return nil
}
// verifyConnection is for use as a tls.Config.VerifyConnection callback
// to do custom client certificate verification. It is intended for
// installation only by clientauth.ConfigureTLSConfig().
//
// Unlike VerifyPeerCertificate, VerifyConnection is called on every
// connection including resumed sessions, preventing session-resumption bypass.View on GitHub (pinned to 50e54ee279)
Solutions
- Prefer the modern equivalent: tls.client_auth.verifier.leaf with a leaf_cert_loader (inline cert or file) instead of trusted_leaf_certs
- If you must keep the deprecated field, supply base64(STD) of the DER bytes: openssl x509 -in cert.pem -outform der | base64 -w0
- Verify round-trip: echo <value> | base64 -d | openssl x509 -inform der -noout
- Check for line breaks or whitespace corruption inside the base64 string in the JSON
Example fix
# before (deprecated + error-prone JSON)
"client_authentication": {
"trusted_leaf_certs": ["MIIB...pem-text..."],
"mode": "require_and_verify"
}
# after (caddyfile)
client_auth {
mode require_and_verify
verifier leaf {
leaf_cert_file /etc/caddy/client-leaf.pem
}
} Defensive patterns
Strategy: validation
Validate before calling
// Ensure a value is base64(DER) of an X.509 cert before putting it in trusted_leaf_certs
func isBase64DERCert(s string) error {
der, err := base64.StdEncoding.DecodeString(strings.TrimSpace(s))
if err != nil {
return err
}
if _, err := x509.ParseCertificate(der); err != nil {
return fmt.Errorf("not an X.509 DER cert: %w", err)
}
return nil
} Prevention
- Migrate off trusted_leaf_certs entirely — use verifier leaf with a loader
- Encode with: openssl x509 -in cert.pem -outform der | base64 -w0
- Never paste PEM text (dashes/headers) into the base64 field
When it happens
Trigger: Putting a PEM string, a file path, or malformed base64 into the trusted_leaf_certs JSON array instead of base64-encoded DER; values that decode but are not parseable as X.509 certificates.
Common situations: Hand-building JSON configs with trust_leaf_certs copied from a PEM file; scripts that base64-encode the wrong input; migrating configs written for older Caddy versions.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- parsing certificate at index %d: %v
- two policies with same match criteria have conflicting clien
- reading %s: %v
- parsing certificate in %s: %v
- loading client cert verifiers: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/ba7c057c979f848f.
Report an issue: GitHub.