slackhq/nebula · critical
private key is not a pair with public key in nebula cert: %w
Error message
private key is not a pair with public key in nebula cert: %w
What it means
newCertState calls v1.VerifyPrivateKey(curve, privateKey) and the private key in pki.key does not correspond to the public key inside the v1 nebula certificate. The %w wraps the underlying mismatch error.
Source
Thrown at pki.go:423
}
if v1.Curve() != v2.Curve() {
return nil, util.NewContextualError("v1 and v2 curve are not the same, ignoring", nil, nil)
}
if v1.Networks()[0] != v2.Networks()[0] {
return nil, util.NewContextualError("v1 and v2 networks are not the same", nil, nil)
}
cs.initiatingVersion = dv
}
if v1 != nil {
if pkcs11backed {
//NOTE: We do not currently have a method to verify a public private key pair when the private key is in an hsm
} else {
if err := v1.VerifyPrivateKey(privateKeyCurve, privateKey); err != nil {
return nil, fmt.Errorf("private key is not a pair with public key in nebula cert: %w", err)
}
}
v1hs, err := v1.MarshalForHandshakes()
if err != nil {
return nil, fmt.Errorf("error marshalling v1 certificate for handshake: %w", err)
}
ncs, err := newCipherSuite(v1.Curve(), pkcs11backed, cipher, fips140.Enforced())
if err != nil {
return nil, err
}
cs.v1Cert = v1
cs.v1Credential = handshake.NewCredential(v1, v1hs, privateKey, ncs)
if cs.initiatingVersion == 0 {
cs.initiatingVersion = cert.Version1
}
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Re-issue the host certificate signed from the existing pki.key (nebula-cert sign -key pki.key ...) so cert and key match
- Or restore the pki.key that pairs with the current certificate
- Confirm pairing by comparing public keys: nebula-cert print -path pki.cert vs the key's public key
Example fix
// before: cert for host A + key for host B pki: cert: /etc/nebula/hostA.crt key: /etc/nebula/hostB.key // after: regenerate cert from the key you keep nebula-cert sign -ca-crt ca.crt -ca-key ca.key -name hostB -ip 10.0.0.2/24 -key /etc/nebula/pki.key -out-crt /etc/nebula/pki.cert
Defensive patterns
Strategy: validation
Validate before calling
// verify key/cert pairing before starting nebula
func keyMatchesCert(certPath, keyPath string) error {
crtPEM, _ := os.ReadFile(certPath)
keyPEM, _ := os.ReadFile(keyPath)
crt, _, err := cert.UnmarshalCertificateFromPEM(certPEM); if err != nil { return err }
_, _, curve, err := cert.UnmarshalPrivateKeyFromPEM(keyPEM); if err != nil { return err }
return crt.VerifyPrivateKey(curve, keyPEM)
} Try / catch
if err := reloadCerts(); err != nil {
if strings.Contains(err.Error(), "private key is not a pair") {
log.Fatalf("pki.cert and pki.key do not match; re-issue the certificate for this key: %v", err)
}
return err
} Prevention
- Always deploy cert and key as one atomic unit (same directory, same commit)
- Never reuse a cert file from another host
- Verify pairing with nebula-cert print and a key public-key dump during deployment
When it happens
Trigger: newCertState (from newCertStateFromConfig / TestNewFirewallFromConfig): a v1 certificate is present and the loaded pki.key fails VerifyPrivateKey — key and cert belong to different identities.
Common situations: Replaced pki.cert but not pki.key (or vice versa); files from different hosts mixed by config management; wrong key file path pointing to another node's key.
Related errors
- no certificates found in pki.cert
- %s: %w
- can not sign a CA certificate with another
- error computing issuer: %v
- self signed certificates must have IsCA set to true
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/4e44dce79f47965f.
Report an issue: GitHub.