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

  1. Check the CA's `intermediate` sub-directive: the cert file must exist, be valid PEM, and be readable by Caddy.
  2. Delete the internal CA's stored intermediate data so it is regenerated, then reload.
  3. 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

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

Related errors


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