caddyserver/caddy · error

parsing certificate from URL %s: %v

Error message

parsing certificate from URL %s: %v

What it means

The HTTP CA pool downloaded the bundle successfully, but a PEM CERTIFICATE block inside the response body failed x509.ParseCertificate. The endpoint served PEM-framed data that is not valid DER certificate bytes.

Source

Thrown at modules/caddytls/capools.go:706

			return err
		}
		if res.StatusCode < 200 || res.StatusCode >= 300 {
			return fmt.Errorf("HTTP %d fetching CA certificate bundle from %s", res.StatusCode, uri)
		}
		// Parse PEM to extract certificates
		pemData := pembs
		for len(pemData) > 0 {
			var block *pem.Block
			block, pemData = pem.Decode(pemData)
			if block == nil {
				break
			}
			if block.Type != "CERTIFICATE" {
				continue
			}
			cert, err := x509.ParseCertificate(block.Bytes)
			if err != nil {
				return fmt.Errorf("parsing certificate from URL %s: %v", uri, err)
			}
			caPool.AddCert(cert)
			certs = append(certs, cert)
		}
	}
	hcp.pool = caPool
	hcp.certs = certs
	return nil
}

// Syntax:
//
//	trust_pool http [<endpoints...>] {
//			endpoints 	<endpoints...>
//			tls 		<tls_config>
//	}
//
// tls_config:

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Download the body with curl and validate every certificate: `curl -s URL | openssl storeutl -noout -text /dev/stdin` or split blocks and run `openssl x509 -noout -text` on each.
  2. Fix the server-side bundle generation so only complete, valid certificates are served.
  3. If a proxy is mangling the body, bypass it or pin to a `file` trust pool updated out-of-band.

Example fix

# before
trust_pool http https://ca.example.com/bundle   # serves HTML error page with stray PEM

# after
# host a verified bundle:
trust_pool http https://ca.example.com/bundle.pem
Defensive patterns

Strategy: validation

Validate before calling

// verify the served body contains only parseable certificates
func validateBundleBody(body []byte) error {
	rest := body
	n := 0
	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("unparseable certificate in bundle: %w", err)
		}
		n++
	}
	if n == 0 {
		return errors.New("bundle contains no certificates")
	}
	return nil
}

Prevention

When it happens

Trigger: The URL serves an HTML error page with an embedded CERTIFICATE-looking block, a partially-written bundle, a truncated proxy response, or non-certificate DER wrapped in a CERTIFICATE PEM block.

Common situations: CDN/proxy serving a truncated or interpolated body; misconfigured endpoint returning docs pages; bundles regenerated mid-upload; corporate TLS-inspection proxies mangling responses.

Understand the failure class

Related errors


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