slackhq/nebula · error
ErrUnknownSubtype
ErrUnknownSubtype
Error message
unknown handshake subtype
What it means
ErrUnknownSubtype is returned by subtypeInfoFor when asked for pattern info for a handshake subtype number that this build does not know. It indicates a protocol negotiation mismatch: the peer referenced a handshake pattern variant that is not registered locally. The error is wrapped with the offending subtype number via fmt.Errorf.
Source
Thrown at handshake/errors.go:13
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
- Upgrade this library so both peers support the same set of handshake subtypes
- Pin both deployments to a version with matching pattern tables
- If the packet is unexpected or untrusted, drop the connection and log the peer address
Example fix
// before: peer negotiated subtype 99 (unsupported here) // after: align versions and configure both peers to an agreed subtype $ go get github.com/example/mesh@v1.9.0 // adds subtype 99 support // or configure peer to use subtype 1 (XX-like pattern)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := handshake.SubtypeInfoFor(subtype); err != nil {
// reject or negotiate down before starting the handshake
return fmt.Errorf("peer requested unsupported subtype %d", subtype)
} Type guard
func subtypeSupported(subtype byte) bool {
_, err := handshake.SubtypeInfoFor(subtype)
return err == nil
} Try / catch
info, err := handshake.SubtypeInfoFor(hdr.Subtype)
if errors.Is(err, handshake.ErrUnknownSubtype) {
conn.Close()
log.Printf("unsupported handshake subtype %d from %s", hdr.Subtype, conn.RemoteAddr())
return
} Prevention
- Pin all nodes to library versions supporting the same subtype set
- Negotiate the highest mutually supported subtype before handshaking
- Alert on unknown subtype hits — likely version skew or hostile traffic
When it happens
Trigger: subtypeInfoFor(99) in handshake/patterns.go:53 has no entry for the given subtype byte from an incoming packet's header; covered by patterns_test.go:45.
Common situations: Peer runs a newer/older library version supporting additional handshake subtypes; a corrupted or attacker-crafted packet carries a bogus subtype byte; misconfigured listeners speaking a different pattern variant.
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/db314b20562d4e01.
Report an issue: GitHub.