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
- 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.
- Fix the server-side bundle generation so only complete, valid certificates are served.
- 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
- Generate bundles programmatically from real certificates; never hand-edit.
- Serve bundles with Content-Length set and disable any HTML error-page injection on that path.
- Checksum published bundles and alert on drift.
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
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- parsing certificate '%s': %v
- CA %s has no root certificate
- CA %s has a nil certificate in its intermediate chain
- HTTP %d fetching CA certificate bundle from %s
- WebSocket connections aren't allowed.
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/d7b7ee6e76a37e2a.
Report an issue: GitHub.