caddyserver/caddy · critical

generating new intermediate cert: %v

Error message

generating new intermediate cert: %v

What it means

When no intermediate exists in storage, Caddy generates one: CA.genIntermediate has generateIntermediate sign a new intermediate cert with the root (lifetime = IntermediateLifetime, forced below root remaining lifetime by the check at ca.go:172). Any failure in that signing path is wrapped as 'generating new intermediate cert'. This blocks leaf-certificate issuance entirely, since leafs are signed by the intermediate by default.

Source

Thrown at modules/caddypki/ca.go:356

	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)
		}
	}

	if interKey == nil {
		interKeyPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyIntermediateKey())
		if err != nil {
			return nil, nil, fmt.Errorf("loading intermediate key: %v", err)
		}
		interKey, err = certmagic.PEMDecodePrivateKey(interKeyPEM)

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Ensure entropy availability and retry provisioning.
  2. Check the root cert/key pair actually matches (openssl pubkey comparison) — a mismatch can make signing fail.
  3. Use plain ASCII for intermediate_common_name.
  4. Upgrade Caddy; if it persists, capture the wrapped inner error (it names the exact signing step) and report upstream.
Defensive patterns

Strategy: retry

Validate before calling

// Before relying on a CA for issuance, verify its root can sign: pair check
if !pubKeysMatch(rootCert, rootKey) { fail("root pair mismatch; cannot generate intermediate") }

Type guard

func pubKeysMatch(cert *x509.Certificate, key crypto.Signer) bool {
    return cert.PublicKey.(interface{ Equal(crypto.PublicKey) bool }).Equal(key.Public())
}

Try / catch

if strings.Contains(err.Error(), "generating new intermediate cert") {
    // check root pairing + entropy, retry once; keep leaf issuance disabled meanwhile
}

Prevention

When it happens

Trigger: First use of a CA (no intermediate in storage) and generateIntermediate fails: root key unusable for signing, entropy/RNG failure, x509 template error (IntermediateCommonName expansion), or an internal smallstep error while signing with the root.

Common situations: Entropy-starved containers during provisioning; an imported root whose key algorithm mismatches its cert; odd characters/templates in intermediate_common_name; version regressions in the bundled step-ca library.

Related errors


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