caddyserver/caddy · error

parsing certificate in %s: %v

Error message

parsing certificate in %s: %v

What it means

FileCAPool.Provision successfully read the PEM file and found CERTIFICATE blocks, but x509.ParseCertificate failed on one block's DER payload. The file exists and is PEM-shaped, yet at least one certificate inside is corrupt or truncated — the wrapped error gives the precise parse failure.

Source

Thrown at modules/caddytls/capools.go:167

	var certs []*x509.Certificate
	for _, pemFile := range f.TrustedCACertPEMFiles {
		pemContents, err := os.ReadFile(pemFile)
		if err != nil {
			return fmt.Errorf("reading %s: %v", pemFile, err)
		}
		// Parse PEM to extract certificates
		for len(pemContents) > 0 {
			var block *pem.Block
			block, pemContents = pem.Decode(pemContents)
			if block == nil {
				break
			}
			if block.Type != "CERTIFICATE" {
				continue
			}
			cert, err := x509.ParseCertificate(block.Bytes)
			if err != nil {
				return fmt.Errorf("parsing certificate in %s: %v", pemFile, err)
			}
			caPool.AddCert(cert)
			certs = append(certs, cert)
		}
	}
	f.pool = caPool
	f.certs = certs
	return nil
}

// Syntax:
//
//	trust_pool file [<pem_file>...] {
//		pem_file <pem_file>...
//	}
//
// The 'pem_file' directive can be specified multiple times.
func (fcap *FileCAPool) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Validate each certificate in the file: openssl crl2pkcs7 -nocrl -certfile ca.pem | openssl pkcs7 -print_certs -noout, or split the bundle and parse each block with openssl x509 -noout -in <block>.
  2. Re-download or re-export the CA bundle from the authoritative source.
  3. If the bundle contains PKCS#7 content, convert first: openssl pkcs7 -in bundle.p7b -print_certs -out ca.pem.
  4. Remove non-certificate blocks (keys, CSRs) from the file.

Example fix

# before: corrupt block inside bundle
# (one BEGIN/END CERTIFICATE section is truncated)

# after: regenerate a clean PEM bundle
openssl pkcs7 -in bundle.p7b -print_certs -out /etc/caddy/ca.pem
# then verify every cert parses:
awk 'BEGIN{c=0} /BEGIN CERT/{c++} /END CERT/{print "cert",c}' /etc/caddy/ca.pem
openssl crl2pkcs7 -nocrl -certfile /etc/caddy/ca.pem | openssl pkcs7 -print_certs -noout
Defensive patterns

Strategy: validation

Validate before calling

// Verify every CERTIFICATE block parses before Caddy loads the file.
data, _ := os.ReadFile(pemFile)
rest := data
for {
    var block *pem.Block
    block, rest = pem.Decode(rest)
    if block == nil {
        break
    }
    if block.Type != "CERTIFICATE" {
        continue
    }
    if _, err := x509.ParseCertificate(block.Bytes); err != nil {
        return fmt.Errorf("bad cert in %s: %v", pemFile, err)
    }
}

Prevention

When it happens

Trigger: A trusted CA PEM file where a certificate was partially overwritten, has flipped bytes from a bad copy-paste (line truncation, missing base64 padding), or contains a CERTIFICATE block that is not actually X.509 (e.g. a converted key or CSR mislabeled as a certificate).

Common situations: Hand-concatenated CA bundles with a broken intermediate; files edited in place where one line got mangled; certificate chains downloaded in the wrong format (PKCS#7 saved as .pem without conversion).

Understand the failure class

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/abe7ba7408f3bfb6. Report an issue: GitHub.