caddyserver/caddy · error

can't parse the given certificate: %s

Error message

can't parse the given certificate: %s

What it means

VerifyClientCertificate takes rawCerts[0] (the client's leaf certificate as sent on the wire) and parses it with x509.ParseCertificate; a parse failure is wrapped as 'can't parse the given certificate'. The bytes came from the TLS peer, so this indicates the peer sent malformed certificate data rather than a config problem.

Source

Thrown at modules/caddytls/connpolicy.go:1038

		if !ok {
			return fmt.Errorf("leaf module '%s' is not a leaf certificate loader", vMod)
		}
		l.LeafCertificateLoadersRaw = append(
			l.LeafCertificateLoadersRaw,
			caddyconfig.JSONModuleObject(vMod, "loader", modName, nil),
		)
	}
	return nil
}

func (l LeafCertClientAuth) VerifyClientCertificate(rawCerts [][]byte, _ [][]*x509.Certificate) error {
	if len(rawCerts) == 0 {
		return fmt.Errorf("no client certificate provided")
	}

	remoteLeafCert, err := x509.ParseCertificate(rawCerts[0])
	if err != nil {
		return fmt.Errorf("can't parse the given certificate: %s", err.Error())
	}

	if slices.ContainsFunc(l.trustedLeafCerts, remoteLeafCert.Equal) {
		return nil
	}

	return fmt.Errorf("client leaf certificate failed validation")
}

// PublicKeyAlgorithm is a JSON-unmarshalable wrapper type.
type PublicKeyAlgorithm x509.PublicKeyAlgorithm

// UnmarshalJSON satisfies json.Unmarshaler.
func (a *PublicKeyAlgorithm) UnmarshalJSON(b []byte) error {
	algoStr := strings.ToLower(strings.Trim(string(b), `"`))
	algo, ok := publicKeyAlgorithms[algoStr]
	if !ok {
		return fmt.Errorf("unrecognized public key algorithm: %s (expected one of %v)",

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Reproduce with a known-good client (openssl s_client -connect host:443 -cert client.pem -key client.key) to confirm the server config is fine
  2. Inspect what the peer sends: capture with tcpdump and decode the Certificate handshake message
  3. Fix or update the offending client's certificate serialization
  4. If behind a proxy/terminator, verify it forwards the original client certificate bytes unchanged
Defensive patterns

Strategy: try-catch

Try / catch

// If you build custom verifiers on top of x509.ParseCertificate
if _, err := x509.ParseCertificate(rawCerts[0]); err != nil {
	// peer sent malformed certificate bytes; reject and log peer identity (IP/SNI)
	return fmt.Errorf("peer sent unparseable certificate: %w", err)
}

Prevention

When it happens

Trigger: A TLS client presenting a corrupted, truncated, or non-X.509 certificate; hand-rolled TLS clients that put arbitrary bytes in the Certificate message; middleboxes/terminators that mangle the chain.

Common situations: Custom TLS implementations or load tests (e.g. raw TLS scripts) sending garbage; proxies that re-encode certificates badly; extremely rare with mainstream clients — treat as peer-side fault or tampering.

Understand the failure class

Related errors


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