{"record":{"id":"9c740dc58c108b79","repo":"netbirdio/netbird","slug":"invalid-magic-header","errorCode":null,"errorMessage":"invalid magic header","messagePattern":"invalid magic header","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/relay/messages/message.go","lineNumber":173,"sourceCode":"\n\tmsg := make([]byte, headerTotalSizeAuth+len(authPayload))\n\tmsg[0] = byte(CurrentProtocolVersion)\n\tmsg[1] = byte(MsgTypeAuth)\n\tcopy(msg[sizeOfProtoHeader:], magicHeader)\n\tcopy(msg[offsetAuthPeerID:], peerID[:])\n\tcopy(msg[headerTotalSizeAuth:], authPayload)\n\treturn msg, nil\n}\n\n// UnmarshalAuthMsg extracts peerID and the auth payload from the message\nfunc UnmarshalAuthMsg(msg []byte) (*PeerID, []byte, error) {\n\tif len(msg) < headerTotalSizeAuth {\n\t\treturn nil, nil, ErrInvalidMessageLength\n\t}\n\n\t// Validate the magic header\n\tif !bytes.Equal(msg[offsetMagicByte:offsetMagicByte+sizeOfMagicByte], magicHeader) {\n\t\treturn nil, nil, errors.New(\"invalid magic header\")\n\t}\n\n\tpeerID := PeerID(msg[offsetAuthPeerID:headerTotalSizeAuth])\n\treturn &peerID, msg[headerTotalSizeAuth:], nil\n}\n\n// MarshalAuthResponse creates a response message to the auth.\n// In case of success connection the server response with a AuthResponse message. This message contains the server's\n// instance URL. This URL will be used by choose the common Relay server in case if the peers are in different Relay\n// servers.\nfunc MarshalAuthResponse(address string) ([]byte, error) {\n\tab := []byte(address)\n\tmsg := make([]byte, sizeOfProtoHeader, sizeOfProtoHeader+len(ab))\n\n\tmsg[0] = byte(CurrentProtocolVersion)\n\tmsg[1] = byte(MsgTypeAuthResponse)\n\n\tmsg = append(msg, ab...)","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/shared/relay/messages/message.go#L155-L191","documentation":"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.","triggerScenarios":"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.","commonSituations":"Port mismatches in self-hosted docker-compose deployments; custom readers consuming bytes before the unmarshal call; middleboxes altering payloads on cleartext connections.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"wantMagic := []byte{0x21, 0x12, 0xA4, 0x42}\nif !bytes.Equal(buf[offsetMagicByte:offsetMagicByte+4], wantMagic) {\n\treturn fmt.Errorf(\"endpoint is not speaking the NetBird relay protocol; check host/port\")\n}","typeGuard":"func looksLikeRelayFrame(buf []byte) bool {\n\tmagic := []byte{0x21, 0x12, 0xA4, 0x42}\n\treturn len(buf) >= 8 && bytes.Equal(buf[4:8], magic)\n}","tryCatchPattern":"if _, _, err := messages.UnmarshalAuthMsg(buf); err != nil {\n\tif err.Error() == \"invalid magic header\" {\n\t\t// wrong service or misaligned stream: verify endpoint and framing, do not retry blindly\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["relay","protocol","magic-header","framing"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}