netbirdio/netbird · error
invalid magic header
Error message
invalid magic header
What it means
UnmarshalAuthMsg requires bytes at the magic-byte offset to equal the constant 0x21 0x12 0xA4 0x42 (the STUN magic cookie NetBird reuses). The length check already passed, but the magic mismatch means the buffer is not a NetBird relay auth message: wrong endpoint, corrupted stream, or misaligned framing offsets.
Source
Thrown at shared/relay/messages/message.go:173
msg := make([]byte, headerTotalSizeAuth+len(authPayload))
msg[0] = byte(CurrentProtocolVersion)
msg[1] = byte(MsgTypeAuth)
copy(msg[sizeOfProtoHeader:], magicHeader)
copy(msg[offsetAuthPeerID:], peerID[:])
copy(msg[headerTotalSizeAuth:], authPayload)
return msg, nil
}
// UnmarshalAuthMsg extracts peerID and the auth payload from the message
func UnmarshalAuthMsg(msg []byte) (*PeerID, []byte, error) {
if len(msg) < headerTotalSizeAuth {
return nil, nil, ErrInvalidMessageLength
}
// Validate the magic header
if !bytes.Equal(msg[offsetMagicByte:offsetMagicByte+sizeOfMagicByte], magicHeader) {
return nil, nil, errors.New("invalid magic header")
}
peerID := PeerID(msg[offsetAuthPeerID:headerTotalSizeAuth])
return &peerID, msg[headerTotalSizeAuth:], nil
}
// MarshalAuthResponse creates a response message to the auth.
// In case of success connection the server response with a AuthResponse message. This message contains the server's
// instance URL. This URL will be used by choose the common Relay server in case if the peers are in different Relay
// servers.
func MarshalAuthResponse(address string) ([]byte, error) {
ab := []byte(address)
msg := make([]byte, sizeOfProtoHeader, sizeOfProtoHeader+len(ab))
msg[0] = byte(CurrentProtocolVersion)
msg[1] = byte(MsgTypeAuthResponse)
msg = append(msg, ab...)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Verify the target is a NetBird relay service on the correct port
- Check framing offsets: the magic sits after the protocol header, not at offset 0
- Hex-dump the first bytes of the received frame to confirm what is actually arriving
Defensive patterns
Strategy: validation
Validate before calling
wantMagic := []byte{0x21, 0x12, 0xA4, 0x42}
if !bytes.Equal(buf[offsetMagicByte:offsetMagicByte+4], wantMagic) {
return fmt.Errorf("endpoint is not speaking the NetBird relay protocol; check host/port")
} Type guard
func looksLikeRelayFrame(buf []byte) bool {
magic := []byte{0x21, 0x12, 0xA4, 0x42}
return len(buf) >= 8 && bytes.Equal(buf[4:8], magic)
} Try / catch
if _, _, err := messages.UnmarshalAuthMsg(buf); err != nil {
if err.Error() == "invalid magic header" {
// wrong service or misaligned stream: verify endpoint and framing, do not retry blindly
}
return err
} Prevention
- Verify relay host/port against the deployment before connecting
- Consume exactly the frame bytes your reader produced before unmarshalling
- Hex-dump the first frame when integrating against the relay protocol
When it happens
Trigger: Pointing the relay client at a non-relay service (signal, HTTP) on the wrong port; stream byte-offset drift from an earlier framing bug; payloads rewritten in transit.
Common situations: Port mismatches in self-hosted docker-compose deployments; custom readers consuming bytes before the unmarshal call; middleboxes altering payloads on cleartext connections.
Related errors
- invalid message length
- invalid token data
- invalid token data: insufficient length
- invalid payload: insufficient length
- invalid signature
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/9c740dc58c108b79.
Report an issue: GitHub.