slackhq/nebula · error

ErrNoPeerStaticKey

ErrNoPeerStaticKey

Error message

no peer static key was present

What it means

ErrNoPeerStaticKey is returned by Recombine when the publicKey argument is nil. Recombine reassembles a peer certificate from its raw bytes plus the peer's static public key; without that key the certificate cannot be completed, so the call fails fast.

Source

Thrown at cert/errors.go:34

	ErrSignatureMismatch          = errors.New("certificate signature did not match")
	ErrInvalidPublicKey           = errors.New("invalid public key")
	ErrInvalidPrivateKey          = errors.New("invalid private key")
	ErrPublicPrivateCurveMismatch = errors.New("public key does not match private key curve")
	ErrPublicPrivateKeyMismatch   = errors.New("public key and private key are not a pair")
	ErrPrivateKeyEncrypted        = errors.New("private key must be decrypted")
	ErrCaNotFound                 = errors.New("could not find ca for the certificate")
	ErrUnknownVersion             = errors.New("certificate version unrecognized")
	ErrCertPubkeyPresent          = errors.New("certificate has unexpected pubkey present")
	ErrCurveMismatch              = errors.New("certificate curve does not match CA")

	ErrInvalidPEMBlock                   = errors.New("input did not contain a valid PEM encoded block")
	ErrInvalidPEMCertificateBanner       = errors.New("bytes did not contain a proper certificate banner")
	ErrInvalidPEMX25519PublicKeyBanner   = errors.New("bytes did not contain a proper X25519 public key banner")
	ErrInvalidPEMX25519PrivateKeyBanner  = errors.New("bytes did not contain a proper X25519 private key banner")
	ErrInvalidPEMEd25519PublicKeyBanner  = errors.New("bytes did not contain a proper Ed25519 public key banner")
	ErrInvalidPEMEd25519PrivateKeyBanner = errors.New("bytes did not contain a proper Ed25519 private key banner")

	ErrNoPeerStaticKey = errors.New("no peer static key was present")
	ErrNoPayload       = errors.New("provided payload was empty")

	ErrMissingDetails  = errors.New("certificate did not contain details")
	ErrEmptySignature  = errors.New("empty signature")
	ErrEmptyRawDetails = errors.New("empty rawDetails not allowed")
)

type ErrInvalidCertificateProperties struct {
	str string
}

func NewErrInvalidCertificateProperties(format string, a ...any) error {
	return &ErrInvalidCertificateProperties{fmt.Sprintf(format, a...)}
}

func (e *ErrInvalidCertificateProperties) Error() string {
	return e.str
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Ensure the peer's static public key is loaded and non-nil before calling Recombine
  2. Fix upstream key loading (config/env/file) so the peer key bytes are actually populated
  3. Return/handle the missing-key condition earlier in the handshake flow instead of calling Recombine

Example fix

// before
cert, err := Recombine(v, raw, peerPub, curve) // peerPub == nil
// after
if peerPub == nil {
    return nil, fmt.Errorf("peer static key missing")
}
cert, err := Recombine(v, raw, peerPub, curve)
Defensive patterns

Strategy: validation

Validate before calling

if publicKey == nil {
    return fmt.Errorf("peer static key missing; cannot Recombine")
}

Type guard

func hasPeerKey(b []byte) bool { return len(b) > 0 }

Try / catch

c, err := cert.Recombine(v, raw, peerPub, curve)
if errors.Is(err, cert.ErrNoPeerStaticKey) {
    // defer until the peer's key exchange message arrives
}

Prevention

When it happens

Trigger: Calling cert.Recombine(version, rawCertBytes, nil, curve) — i.e. the peer's static public key slice is nil, typically because key loading failed or was skipped earlier.

Common situations: Peer handshake data missing the static key field; config where the peer public key env var is unset; deserialization of handshake messages that omitted the key; attempting Recombine before receiving the peer's key exchange message.

Related errors


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