caddyserver/caddy · error
loading intermediate cert: %v
Error message
loading intermediate cert: %v
What it means
CA.loadOrGenIntermediate reads the intermediate certificate PEM from storage (storageKeyIntermediateCert). A non-ErrNotExist error — backend failure, permissions, I/O fault — is wrapped as 'loading intermediate cert'. A clean not-found instead triggers intermediate generation, so this error means storage is present but failing to serve the object.
Source
Thrown at modules/caddypki/ca.go:350
}
rootKeyPEM, err := certmagic.PEMEncodePrivateKey(rootKey)
if err != nil {
return nil, nil, fmt.Errorf("encoding root key: %v", err)
}
err = ca.storage.Store(ca.ctx, ca.storageKeyRootKey(), rootKeyPEM)
if err != nil {
return nil, nil, fmt.Errorf("saving root key: %v", err)
}
return rootCert, rootKey, nil
}
func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Signer) (interCertChain []*x509.Certificate, interKey crypto.Signer, err error) {
var interCert *x509.Certificate
interCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyIntermediateCert())
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return nil, nil, fmt.Errorf("loading intermediate cert: %v", err)
}
// TODO: should we require that all or none of the assets are required before overwriting anything?
interCert, interKey, err = ca.genIntermediate(rootCert, rootKey)
if err != nil {
return nil, nil, fmt.Errorf("generating new intermediate cert: %v", err)
}
interCertChain = append(interCertChain, interCert)
}
if len(interCertChain) == 0 {
interCertChain, err = pemDecodeCertificateChain(interCertPEM)
if err != nil {
return nil, nil, fmt.Errorf("decoding intermediate certificate PEM: %v", err)
}
}
View on GitHub (pinned to 50e54ee279)
Solutions
- Repair read access to the storage location and confirm the intermediate object is present and readable.
- Restore backend connectivity/credentials for custom storage, then restart.
- Validate the object is intact (openssl x509 -noout); if corrupt, delete the intermediate cert+key objects only (keep root) so Caddy regenerates the intermediate signed by the existing root.
- Point storage at a writable, healthy location if the backend is unreliable.
Defensive patterns
Strategy: retry
Validate before calling
// Pre-start readability check for the intermediate object (skip if absent = OK)
if _, err := os.ReadFile(caDir + "/intermediate.crt"); err != nil && !errors.Is(err, fs.ErrNotExist) {
log.Fatalf("storage failing for intermediate cert: %v", err)
} Try / catch
// transient backend failures: one bounded retry, then fail with context
if strings.Contains(err.Error(), "loading intermediate cert") {
if err2 := retryOnce(startCaddy, cfg); err2 != nil { return fmt.Errorf("storage failing: %w", err2) }
} Prevention
- Include CA asset reads in storage healthchecks.
- Keep the Caddy service user's read permissions intact across system updates.
- Use caddy storage export/import for migrations instead of raw object copies.
When it happens
Trigger: storage.Load for the intermediate cert errors with something other than fs.ErrNotExist: unreadable file, custom storage backend outage, corrupted storage index. Happens whenever a CA loads an existing intermediate (normal subsequent startups) in the default (non-external-intermediate, non-sign_with_root) configuration.
Common situations: Service user lacking read permission on storage/caddy/pki/<id>/ca/intermediate.crt; Redis/consul/S3 briefly down at boot; migrated storage where the object metadata broke.
Related errors
- loading root cert: %v
- saving root certificate: %v
- failed to get root and intermediate cert for CA %s: %v
- failed to provision CA %s, %w
- loading storage module: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/fec7e71c2e64037f.
Report an issue: GitHub.