slackhq/nebula · error
recombine cert: %w
Error message
recombine cert: %w
What it means
validateCert wraps errors from cert.Recombine as 'recombine cert: %w'. Recombine merges the peer's certificate bytes with the peer's Noise static key to reconstruct the full certificate and validate it cryptographically. Failure means the cert bytes, peer static key, curve, or network (CA) don't fit together — the presented certificate cannot be recombined for the given curve/version.
Source
Thrown at handshake/machine.go:356
return nil
}
func (m *Machine) validateCert(payload Payload) error {
cred := m.getCred(m.myVersion)
if cred == nil {
m.failed = true
return fmt.Errorf("%w: %v", ErrNoCredential, m.myVersion)
}
rc, err := cert.Recombine(
cert.Version(payload.CertVersion),
payload.Cert,
m.hs.PeerStatic(),
cred.Cert.Curve(),
)
if err != nil {
m.failed = true
return fmt.Errorf("recombine cert: %w", err)
}
if !bytes.Equal(rc.PublicKey(), m.hs.PeerStatic()) {
m.failed = true
return ErrPublicKeyMismatch
}
// Version negotiation, if the peer sent a different version and we have it, switch
if rc.Version() != m.myVersion {
if m.getCred(rc.Version()) != nil {
m.myVersion = rc.Version()
}
}
verified, err := m.verifier(rc)
if err != nil {
m.failed = true
return fmt.Errorf("verify cert: %w", err)View on GitHub (pinned to dd8f660c0a)
Solutions
- Re-issue the peer's certificate with nebula-cert matching the CA's curve and version
- Confirm all hosts use certs signed by the same CA and curve family
- Upgrade peers so certificate encoding versions match
- Replace the cert payload source — if this is a middlebox/proxy issue, verify end-to-end packet integrity
Example fix
// before: CA on curve25519, node cert issued as P-256 nebula-cert sign -name host -curve P256 ... // after: match the CA curve nebula-cert sign -ca ca.crt -key ca.key -name host -ip 10.0.0.2/24 -curve CURVE25519
Defensive patterns
Strategy: validation
Validate before calling
// before deployment, check cert/CA curve compatibility
caCert, _ := cert.UnmarshalNebulaCertificate(caPEM)
hostCert, _ := cert.UnmarshalNebulaCertificate(hostPEM)
if caCert.Curve() != hostCert.Curve() {
return fmt.Errorf("cert curve %v does not match CA curve %v", hostCert.Curve(), caCert.Curve())
} Try / catch
_, _, err := machine.ProcessPacket(pkt)
if err != nil && strings.Contains(err.Error(), "recombine cert:") {
// peer cert unusable for this curve/version — reject and reissue peer cert
} Prevention
- Issue all node certs with the same nebula-cert version and curve as the CA
- Validate the full chain (CA + leaf) in CI with nebula-cert before rollout
- Never accept certs from external tooling without verifying curve and format
- Keep CA and node cert versions in lockstep during upgrades
When it happens
Trigger: ProcessPacket -> processPayload -> validateCert where cert.Recombine(cert.Version(payload.CertVersion), payload.Cert, m.hs.PeerStatic(), cred.Cert.Curve(), ...) errors — cert version mismatch with curve, malformed cert bytes in the payload, or peer static key inconsistent with the certificate's signature.
Common situations: Peer certificate issued for a different elliptic curve (P-256 vs curve25519) than the CA, tampered/forged cert payload, cert bytes truncated by an intermediary, incompatible nebula-cert versions between CA and node certs.
Related errors
- ErrPublicKeyMismatch
- curve in cert and private key supplied don't match
- %w: %v
- verify cert: %w
- ErrNoCredential
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/013aebcf127a3f6c.
Report an issue: GitHub.