caddyserver/caddy · error

no CERTIFICATE pem block found in %s

Error message

no CERTIFICATE pem block found in %s

What it means

Returned by convertPEMFilesToDER, used when a Caddyfile trusted_ca_cert_file (or trusted_leaf_cert_file) is read: the file was read successfully but contains either zero PEM blocks or a block whose type is not CERTIFICATE (e.g. a private key or a CSR). The filename in the message identifies the offending file.

Source

Thrown at modules/caddytls/connpolicy.go:764

	if len(ca.TrustedCACerts) > 0 {
		fileMod := &InlineCAPool{}
		fileMod.TrustedCACerts = append(fileMod.TrustedCACerts, ca.TrustedCACerts...)
		ca.CARaw = caddyconfig.JSONModuleObject(fileMod, "provider", "inline", nil)
		ca.TrustedCACertPEMFiles, ca.TrustedCACerts = nil, nil
	}
	return nil
}

func convertPEMFilesToDER(filename string) ([]string, error) {
	certDataPEM, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	var ders []string
	// while block is not nil, we have more certificates in the file
	for block, rest := pem.Decode(certDataPEM); block != nil; block, rest = pem.Decode(rest) {
		if block.Type != "CERTIFICATE" {
			return nil, fmt.Errorf("no CERTIFICATE pem block found in %s", filename)
		}
		ders = append(
			ders,
			base64.StdEncoding.EncodeToString(block.Bytes),
		)
	}
	// if we decoded nothing, return an error
	if len(ders) == 0 {
		return nil, fmt.Errorf("no CERTIFICATE pem block found in %s", filename)
	}
	return ders, nil
}

func (clientauth *ClientAuthentication) provision(ctx caddy.Context) error {
	if len(clientauth.CARaw) > 0 && (len(clientauth.TrustedCACerts) > 0 || len(clientauth.TrustedCACertPEMFiles) > 0) {
		return fmt.Errorf("conflicting config for client authentication trust CA")
	}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Inspect the file: 'openssl x509 -in <file> -text -noout' should parse it as PEM (or grep for BEGIN CERTIFICATE)
  2. If it is DER, convert: 'openssl x509 -inform der -in cert.der -out cert.pem'
  3. Remove any PRIVATE KEY or other non-certificate blocks from the file
  4. Re-download the CA bundle if it is empty or truncated

Example fix

# before
client_auth {
	trusted_ca_cert_file /etc/candy/ca.pem # typo'd dir -> empty file
}

# after
client_auth {
	trusted_ca_cert_file /etc/caddy/ca.pem
}
Defensive patterns

Strategy: validation

Validate before calling

# Validate a CA file before referencing it in config:
openssl x509 -in /etc/caddy/ca.pem -noout >/dev/null 2>&1 \
  && echo OK || echo "not a PEM certificate file"

Prevention

When it happens

Trigger: Pointing trusted_ca_cert_file at: an empty file, a DER (binary) certificate instead of PEM, a file containing a PRIVATE KEY block, or a file with only non-CERTIFICATE PEM blocks. Every block in the file must be a CERTIFICATE block.

Common situations: Operator passes the server's fullchain.pem where a CA bundle was expected and it still parses until a non-cert block appears; file is actually DER-encoded; file truncated to zero bytes by a failed provisioner; correct path but wrong file (key file).

Understand the failure class

Related errors


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