caddyserver/caddy · error

loading intermediate cert

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.

Solutions

  1. Repair read access to the storage location and confirm the intermediate object is present and readable.
  2. Restore backend connectivity/credentials for custom storage, then restart.
  3. 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.
  4. 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

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


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

Appendix: 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)