slackhq/nebula · critical

no valid CA certificates present

Error message

no valid CA certificates present

What it means

When pki.ca is a bundle containing multiple CAs, loadCAPoolFromConfig counts expired entries; if every CA in the pool is expired, none can anchor trust, so it returns this error. It indicates the CA material loaded successfully but is unusable because it has all expired.

Source

Thrown at pki.go:570

		caReader, err = os.Open(caPathOrPEM)
		if err != nil {
			return nil, fmt.Errorf("unable to read pki.ca file %s: %s", caPathOrPEM, err)
		}
	}
	defer caReader.Close()

	caPool, err := cert.NewCAPoolFromPEMReader(caReader)
	if errors.Is(err, cert.ErrExpired) {
		var expired int
		for _, crt := range caPool.CAs {
			if crt.Certificate.Expired(time.Now()) {
				expired++
				l.Warn("expired certificate present in CA pool", "cert", crt)
			}
		}

		if expired >= len(caPool.CAs) {
			return nil, errors.New("no valid CA certificates present")
		}

	} else if err != nil {
		return nil, fmt.Errorf("error while adding CA certificate to CA trust store: %s", err)
	}

	bl := c.GetStringSlice("pki.blocklist", []string{})
	if len(bl) > 0 {
		for _, fp := range bl {
			caPool.BlocklistFingerprint(fp)
		}

		l.Info("Blocklisted certificates", "fingerprintCount", len(bl))
	}

	return caPool, nil
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Re-issue a new CA with nebula-cert ca and re-sign/re-issue host certificates, then update pki.ca.
  2. Check host clock (NTP) to rule out skew causing the expiry check to fail.
  3. Audit CA bundle: remove expired entries and add the current active CA.

Example fix

// regenerate CA and certs
// before: pki.ca: /etc/nebula/ca.crt (expired)
// after:  pki.ca: /etc/nebula/ca-new.crt
$ nebula-cert ca -name "Nebula CA" -duration 87600h
$ nebula-cert sign -ca ca-new.crt -ca-key ca-new.key -name host -out-pub host.crt
Defensive patterns

Strategy: validation

Validate before calling

pool, err := cert.NewCAPoolFromBytes(caPEM)
if err != nil && !errors.Is(err, cert.ErrExpired) {
    return err
}
for _, ca := range pool.CAs {
    if time.Now().After(ca.Details.NotAfter) {
        return errors.New("CA in pki.ca is expired: rotate the CA")
    }
}

Try / catch

if err := reloadCAPool(l, c); err != nil {
    if strings.Contains(err.Error(), "no valid CA certificates") {
        log.Fatal("all CAs in pki.ca are expired; issue a new CA and re-sign host certs")
    }
}

Prevention

When it happens

Trigger: All certificates parsed from pki.ca have NotAfter in the past; expired >= len(caPool.CAs) triggers the error during reloadCAPool.

Common situations: Long-lived deployments where the nebula root CA passed its validity window; clock skew making certs appear expired; copying an old ca.crt after rotating CAs; loading an archived/test CA bundle.

Understand the failure class

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/e0f26ba9cd0783a9. Report an issue: GitHub.