{"record":{"id":"c2bedd8468903ff2","repo":"slackhq/nebula","slug":"can-not-use-pki-initiating-version-1-without-a-v1","errorCode":null,"errorMessage":"can not use pki.initiating_version 1 without a v1 certificate in pki.cert","messagePattern":"can not use pki\\.initiating_version 1 without a v1 certificate in pki\\.cert","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pki.go","lineNumber":380,"sourceCode":"\t}\n\n\tif v1 == nil && v2 == nil {\n\t\treturn nil, errors.New(\"no certificates found in pki.cert\")\n\t}\n\n\tuseInitiatingVersion := uint32(1)\n\tif v1 == nil {\n\t\t// The only condition that requires v2 as the default is if only a v2 certificate is present\n\t\t// We do this to avoid having to configure it specifically in the config file\n\t\tuseInitiatingVersion = 2\n\t}\n\n\trawInitiatingVersion := c.GetUint32(\"pki.initiating_version\", useInitiatingVersion)\n\tvar initiatingVersion cert.Version\n\tswitch rawInitiatingVersion {\n\tcase 1:\n\t\tif v1 == nil {\n\t\t\treturn nil, fmt.Errorf(\"can not use pki.initiating_version 1 without a v1 certificate in pki.cert\")\n\t\t}\n\t\tinitiatingVersion = cert.Version1\n\tcase 2:\n\t\tinitiatingVersion = cert.Version2\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown pki.initiating_version: %v\", rawInitiatingVersion)\n\t}\n\n\treturn newCertState(initiatingVersion, v1, v2, isPkcs11, curve, rawKey, cipher)\n}\n\nfunc newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, privateKeyCurve cert.Curve, privateKey []byte, cipher string) (*CertState, error) {\n\tcs := CertState{\n\t\tprivateKey:               privateKey,\n\t\tpkcs11Backed:             pkcs11backed,\n\t\tcipher:                   cipher,\n\t\tmyVpnNetworksTable:       new(bart.Lite),\n\t\tmyVpnAddrsTable:          new(bart.Lite),","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/pki.go#L362-L398","documentation":"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.","triggerScenarios":"newCertStateFromConfig (via reloadCerts): config has pki.initiating_version: 1 while pki.cert contains only a v2 certificate.","commonSituations":"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.","solutions":["Remove pki.initiating_version from config so it defaults appropriately","Set pki.initiating_version: 2 to match the v2-only certificate","Re-issue a v1 certificate and add it to pki.cert if v1 initiation is truly required"],"exampleFix":"// before (config)\npki:\n  cert: /etc/nebula/pki.cert\n  initiating_version: 1\n// after\npki:\n  cert: /etc/nebula/pki.cert\n  initiating_version: 2","handlingStrategy":"validation","validationCode":"// ensure initiating_version 1 only with a v1 cert present\nfunc checkInitiatingVersion(cfg map[string]any, hasV1 bool) error {\n    if v, ok := cfg[\"pki.initiating_version\"]; ok && v == 1 && !hasV1 {\n        return fmt.Errorf(\"pki.initiating_version 1 requires a v1 certificate\")\n    }\n    return nil\n}","typeGuard":"func canInitiateV1(certs []cert.Certificate) bool {\n    for _, c := range certs { if c.Version() == cert.Version1 { return true } }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Only set pki.initiating_version when you also manage certificate versions explicitly","After removing a v1 cert, remove or bump initiating_version in the same change","Document the cert-version/initiating-version pairing in deployment runbooks"],"tags":["pki","config","handshake"],"backgroundTag":"missing-certificate-for-initiating-version","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}