slackhq/nebula · error
ErrUnexpectedContent
ErrUnexpectedContent
Error message
received unexpected handshake content
What it means
ErrUnexpectedContent is returned by processPayload when a handshake message contains payload data (or certificate data) but the pattern flags say this message should not carry it, or vice versa. It enforces that each message's content matches the expected pattern; the machine is marked failed. The check exists at handshake/machine.go:304 for payloads and :310 for certificates.
Source
Thrown at handshake/errors.go:15
package handshake
import "errors"
var (
ErrInitiateOnResponder = errors.New("initiate called on responder")
ErrInitiateAlreadyCalled = errors.New("initiate already called")
ErrInitiateNotCalled = errors.New("initiate must be called before ProcessPacket for initiators")
ErrPacketTooShort = errors.New("packet too short")
ErrPublicKeyMismatch = errors.New("public key mismatch between certificate and handshake")
ErrIncompleteHandshake = errors.New("handshake completed without receiving required content")
ErrMachineFailed = errors.New("handshake machine has failed")
ErrUnknownSubtype = errors.New("unknown handshake subtype")
ErrMissingContent = errors.New("expected handshake content but message was empty")
ErrUnexpectedContent = errors.New("received unexpected handshake content")
ErrInvalidRemoteIndex = errors.New("peer sent an invalid index in handshake payload")
ErrIndexAllocation = errors.New("failed to allocate local index")
ErrNoCredential = errors.New("no handshake credential available for cert version")
ErrAsymmetricCipherKeys = errors.New("noise produced only one cipher key")
ErrMultiMessageUnsupported = errors.New("multi-message handshake patterns are not yet supported by the manager")
ErrSubtypeMismatch = errors.New("packet subtype does not match handshake machine subtype")
)
View on GitHub (pinned to dd8f660c0a)
Solutions
- Align both peers on the same handshake pattern so content placement matches
- Remove or add payload/cert attachment in the peer's message construction to match the pattern
- Upgrade/downgrade the peer library to a version with matching message layout
Example fix
// before: cert attached to message 1 where pattern expects it in message 2 msg1 := append(m.hs.WriteMessage(), cert...) // after msg1 := m.hs.WriteMessage() msg2 := handshake.AppendCert(m.hs.WriteMessage(), cert)
Defensive patterns
Strategy: validation
Validate before calling
if flags.ExpectsPayload == hasPayload(msg) && flags.ExpectsCert == hasCert(msg) {
// message layout matches pattern; safe to process
} Type guard
func contentMatchesPattern(msg []byte, flags handshake.MsgFlags) bool {
return handshake.HasPayload(msg) == flags.ExpectsPayload &&
handshake.HasCert(msg) == flags.ExpectsCert
} Try / catch
res, err := m.ProcessPacket(out, pkt)
if errors.Is(err, handshake.ErrUnexpectedContent) {
log.Printf("peer %s violates handshake message layout", conn.RemoteAddr())
conn.Close() // protocol violation, not retryable
return
} Prevention
- Standardize the handshake pattern across your fleet configuration
- Reject peers announcing a different pattern version
- Add conformance tests asserting message content per stage
When it happens
Trigger: hasPayloadData != flags.expectsPayload (machine.go:304) or hasCertData != flags.expectsCert (machine.go:310) while processing a decrypted handshake message.
Common situations: Peer library version sends cert in a different message position; hand-rolled or test peer emits extra data; mixing handshake patterns between peers of different configurations.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/93bb5d26ed5d871c.
Report an issue: GitHub.