caddyserver/caddy · error
CA %s has a nil certificate in its intermediate chain
Error message
CA %s has a nil certificate in its intermediate chain
What it means
While collecting IntermediateCertificateChain() from each CA for the pki_intermediate pool, a nil *x509.Certificate appeared in the chain. The pool refuses to add nil entries because they would poison the x509.CertPool used for client verification.
Source
Thrown at modules/caddytls/capools.go:336
pkiApp, err := ctx.AppIfConfigured("pki")
if err != nil {
return fmt.Errorf("pki_intermediate CA pool requires that a PKI app is configured: %v", err)
}
pki := pkiApp.(*caddypki.PKI)
for _, caID := range p.Authority {
c, err := pki.GetCA(ctx, caID)
if err != nil || c == nil {
return fmt.Errorf("getting CA %s: %v", caID, err)
}
p.ca = append(p.ca, c)
}
caPool := x509.NewCertPool()
var certs []*x509.Certificate
for _, ca := range p.ca {
for _, c := range ca.IntermediateCertificateChain() {
if c == nil {
return fmt.Errorf("CA %s has a nil certificate in its intermediate chain", ca.ID)
}
caPool.AddCert(c)
certs = append(certs, c)
}
}
p.pool = caPool
p.certs = certs
return nil
}
// Syntax:
//
// trust_pool pki_intermediate [<ca_name>...] {
// authority <ca_name>...
// }
//
// The 'authority' directive can be specified multiple times.
func (pic *PKIIntermediateCAPool) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {View on GitHub (pinned to 50e54ee279)
Solutions
- Check the CA's `intermediate` sub-directive: the cert file must exist, be valid PEM, and be readable by Caddy.
- Delete the internal CA's stored intermediate data so it is regenerated, then reload.
- In embedded setups, ensure intermediate certificate slices contain no nil entries before provisioning caddytls.
Example fix
# before
{
pki {
ca custom {
intermediate { cert /etc/caddy/broken-intermediate.crt key /etc/caddy/intermediate.key }
}
}
}
# after
{
pki {
ca custom {
intermediate { cert /etc/caddy/intermediate.crt key /etc/caddy/intermediate.key }
}
}
} Defensive patterns
Strategy: validation
Validate before calling
// when building CA chains programmatically, reject nils before provisioning
for _, c := range chain {
if c == nil {
return errors.New("intermediate chain contains nil certificate")
}
} Prevention
- Validate intermediate PEM files with openssl before pointing the pki CA at them.
- Keep intermediate cert+key files atomically deployed (write temp then rename).
- Monitor Caddy's provisioning logs so partial CA state is caught on first load.
When it happens
Trigger: A CA whose intermediate chain contains a nil slot — e.g. an intermediate certificate configured but not yet loaded/parsed (unreadable file, empty PEM), or a programmatically constructed CA whose chain array includes nil.
Common situations: pki CA configured with an `intermediate` block pointing to a missing or corrupt certificate file; storage-level partial writes to the internal CA's intermediate; custom embedding code that builds CA chains manually.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- CA %s has no root certificate
- pki_root CA pool requires that a PKI app is configured: %v
- getting CA %s: %v
- pki_intermediate CA pool requires that a PKI app is configur
- parsing certificate '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/2df1cba676182349.
Report an issue: GitHub.