slackhq/nebula · error

error marshalling v2 certificate for handshake: %w

Error message

error marshalling v2 certificate for handshake: %w

What it means

Wrapping error in newCertState: v2.MarshalForHandshakes failed while preparing the cached wire form of the v2 certificate for handshakes. The v2 cert parsed and its key pair verified, but producing the handshake bytes failed; cause preserved with %w.

Source

Thrown at pki.go:454

		cs.v1Credential = handshake.NewCredential(v1, v1hs, privateKey, ncs)

		if cs.initiatingVersion == 0 {
			cs.initiatingVersion = cert.Version1
		}
	}

	if v2 != 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 := v2.VerifyPrivateKey(privateKeyCurve, privateKey); err != nil {
				return nil, fmt.Errorf("private key is not a pair with public key in nebula cert: %w", err)
			}
		}

		v2hs, err := v2.MarshalForHandshakes()
		if err != nil {
			return nil, fmt.Errorf("error marshalling v2 certificate for handshake: %w", err)
		}
		ncs, err := newCipherSuite(v2.Curve(), pkcs11backed, cipher, fips140.Enforced())
		if err != nil {
			return nil, err
		}
		cs.v2Cert = v2
		cs.v2Credential = handshake.NewCredential(v2, v2hs, privateKey, ncs)

		if cs.initiatingVersion == 0 {
			cs.initiatingVersion = cert.Version2
		}
	}

	var crt cert.Certificate
	crt = cs.getCertificate(cert.Version2)
	if crt == nil {
		// v2 certificates are a superset, only look at v1 if its all we have
		crt = cs.getCertificate(cert.Version1)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Re-generate the v2 certificate with nebula-cert sign and replace pki.cert
  2. Inspect with nebula-cert print -path pki.cert to see the parse failure
  3. Restore pki.cert from a known-good backup

Example fix

// before: corrupted v2 cert in pki.cert
// after
nebula-cert sign -ca-crt ca.crt -ca-key ca.key -name host1 -ip 10.0.0.1/24 -out-crt pki.cert
Defensive patterns

Strategy: validation

Validate before calling

// pre-parse the v2 cert to catch marshal problems early
func validateV2Cert(certPEM []byte) error {
    crt, _, err := cert.UnmarshalCertificateFromPEM(certPEM)
    if err != nil { return err }
    if crt.Version() == cert.Version2 {
        if _, err := crt.MarshalForHandshakes(); err != nil { return err }
    }
    return nil
}

Try / catch

if err := reloadCerts(); err != nil {
    if strings.Contains(err.Error(), "marshalling v2 certificate") {
        log.Fatalf("v2 certificate in pki.cert is corrupt; re-issue it: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: newCertState: a v2 certificate passed private-key verification but v2.MarshalForHandshakes() returned an error — structurally invalid v2 certificate in pki.cert.

Common situations: Corrupted or truncated v2 certificate; certificate emitted by incompatible/buggy tooling; manual edits to the PEM bundle.

Understand the failure class

Related errors


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