slackhq/nebula · error

error while adding CA certificate to CA trust store: %s

Error message

error while adding CA certificate to CA trust store: %s

What it means

When cert.NewCAPoolFromPEMReader returns an error other than the tolerated ErrExpired, loadCAPoolFromConfig wraps it with this message. It means the pki.ca PEM stream contained data that could not be added to the trust store — malformed PEM blocks or unparsable certificates.

Source

Thrown at pki.go:574

	}
	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. Regenerate or re-export ca.crt with 'nebula-cert ca' and ensure it contains only valid Nebula CA certificate PEM blocks
  2. Remove non-certificate PEM blocks (private keys, unrelated certs) from the file
  3. Validate the file with 'nebula-cert print -path ca.crt'
  4. If expired CAs were intended to be skipped, rely on the built-in expired-skipping rather than fixing via this path — this error is for unparsable data, not expiry

Example fix

// before
pki.ca contains: host key block + CA cert block concatenated
// after
pki.ca contains only: -----BEGIN NEBULA CERTIFICATE----- ... (CA cert)
Defensive patterns

Strategy: validation

Validate before calling

f, _ := os.Open(caPath)
defer f.Close()
if _, err := cert.NewCAPoolFromPEMReader(f); err != nil && !errors.Is(err, cert.ErrExpired) {
    return fmt.Errorf("invalid pki.ca: %w", err)
}

Type guard

func caPEMValid(b []byte) bool {
    blk, _ := pem.Decode(b)
    return blk != nil && strings.Contains(blk.Type, "CERTIFICATE")
}

Try / catch

pool, err := loadCAPoolFromConfig(logger, cfg)
if err != nil && strings.Contains(err.Error(), "CA trust store") {
    return fmt.Errorf("pki.ca contains unparsable data: %w", err)
}

Prevention

When it happens

Trigger: reloadCAPool reads a pki.ca whose PEM contains invalid base64, non-certificate blocks, a cert format the parser rejects, or trailing garbage that fails decoding.

Common situations: CA file manually concatenated with other PEM material (keys, intermediate chains in wrong format); copy/paste corruption of inline PEM; CA generated by an incompatible tool/version.

Understand the failure class

Related errors


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