slackhq/nebula · error

can not use pki.initiating_version 1 without a v1 certificat

Error message

can not use pki.initiating_version 1 without a v1 certificate in pki.cert

What it means

pki.initiating_version is set to 1, meaning nebula should initiate handshakes using the v1 certificate, but no v1 certificate is present in pki.cert. Handshake initiation with v1 requires a v1 certificate.

Source

Thrown at pki.go:380

	}

	if v1 == nil && v2 == nil {
		return nil, errors.New("no certificates found in pki.cert")
	}

	useInitiatingVersion := uint32(1)
	if v1 == nil {
		// The only condition that requires v2 as the default is if only a v2 certificate is present
		// We do this to avoid having to configure it specifically in the config file
		useInitiatingVersion = 2
	}

	rawInitiatingVersion := c.GetUint32("pki.initiating_version", useInitiatingVersion)
	var initiatingVersion cert.Version
	switch rawInitiatingVersion {
	case 1:
		if v1 == nil {
			return nil, fmt.Errorf("can not use pki.initiating_version 1 without a v1 certificate in pki.cert")
		}
		initiatingVersion = cert.Version1
	case 2:
		initiatingVersion = cert.Version2
	default:
		return nil, fmt.Errorf("unknown pki.initiating_version: %v", rawInitiatingVersion)
	}

	return newCertState(initiatingVersion, v1, v2, isPkcs11, curve, rawKey, cipher)
}

func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, privateKeyCurve cert.Curve, privateKey []byte, cipher string) (*CertState, error) {
	cs := CertState{
		privateKey:               privateKey,
		pkcs11Backed:             pkcs11backed,
		cipher:                   cipher,
		myVpnNetworksTable:       new(bart.Lite),
		myVpnAddrsTable:          new(bart.Lite),

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Remove pki.initiating_version from config so it defaults appropriately
  2. Set pki.initiating_version: 2 to match the v2-only certificate
  3. Re-issue a v1 certificate and add it to pki.cert if v1 initiation is truly required

Example fix

// before (config)
pki:
  cert: /etc/nebula/pki.cert
  initiating_version: 1
// after
pki:
  cert: /etc/nebula/pki.cert
  initiating_version: 2
Defensive patterns

Strategy: validation

Validate before calling

// ensure initiating_version 1 only with a v1 cert present
func checkInitiatingVersion(cfg map[string]any, hasV1 bool) error {
    if v, ok := cfg["pki.initiating_version"]; ok && v == 1 && !hasV1 {
        return fmt.Errorf("pki.initiating_version 1 requires a v1 certificate")
    }
    return nil
}

Type guard

func canInitiateV1(certs []cert.Certificate) bool {
    for _, c := range certs { if c.Version() == cert.Version1 { return true } }
    return false
}

Prevention

When it happens

Trigger: newCertStateFromConfig (via reloadCerts): config has pki.initiating_version: 1 while pki.cert contains only a v2 certificate.

Common situations: Migrated host has only a v2 cert but stale config still says initiating_version 1; operator toggled handshake version without re-issuing a v1 certificate.

Understand the failure class

Related errors


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