{"record":{"id":"da48f44077885665","repo":"nats-io/nats-server","slug":"w-invalid-version-0x-02x","errorCode":null,"errorMessage":"%w: invalid version 0x%02x","messagePattern":"%w: invalid version 0x%02x","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client_proxyproto.go","lineNumber":325,"sourceCode":"\t// Validate signature (first 12 bytes)\n\tif string(header[:12]) != proxyProtoV2Sig {\n\t\treturn nil, fmt.Errorf(\"%w: invalid signature\", errProxyProtoInvalid)\n\t}\n\n\t// Continue with parsing after signature\n\treturn parseProxyProtoV2Header(conn, header[12:16])\n}\n\n// parseProxyProtoV2Header parses v2 protocol after signature has been validated.\n// header contains the 4 bytes: ver/cmd, fam/proto, addr-len (2 bytes).\nfunc parseProxyProtoV2Header(conn net.Conn, header []byte) (*proxyProtoAddr, error) {\n\t// Parse version and command\n\tverCmd := header[0]\n\tversion := verCmd & proxyProtoV2VerMask\n\tcommand := verCmd & proxyProtoCmdMask\n\n\tif version != proxyProtoV2Ver {\n\t\treturn nil, fmt.Errorf(\"%w: invalid version 0x%02x\", errProxyProtoInvalid, version)\n\t}\n\n\t// Parse address family and protocol\n\tfamProto := header[1]\n\tfamily := famProto & proxyProtoFamilyMask\n\tprotocol := famProto & proxyProtoProtoMask\n\n\t// Parse address length (big-endian uint16)\n\taddrLen := binary.BigEndian.Uint16(header[2:4])\n\n\t// Handle LOCAL command (health check)\n\tif command == proxyProtoCmdLocal {\n\t\t// For LOCAL, we should skip the address data if any\n\t\tif addrLen > 0 {\n\t\t\t// Discard the address data\n\t\t\tif _, err := io.CopyN(io.Discard, conn, int64(addrLen)); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to discard LOCAL command address data: %w\", err)\n\t\t\t}","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L307-L343","documentation":"This error indicates the PROXY protocol v2 header's version nibble does not match the required v2 version (0x2). The version is the high nibble of the ver/cmd byte, masked and compared against proxyProtoV2Ver. It is wrapped in errProxyProtoInvalid, so callers can match it with errors.Is to reject malformed or non-v2 PROXY protocol payloads.","triggerScenarios":"A client (or proxy) sends a binary v2 signature but the ver/cmd byte's high nibble is not 0x2 — e.g. a v1 ASCII 'PROXY ...' line misdetected as v2, a corrupted byte, or a hypothetical v3 header.","commonSituations":"Load balancer (HAProxy, NGINX, AWS NLB) misconfigured to send PROXY v1 text while the server is in v2 binary mode; a raw TCP client fuzzing or sending garbage that happens to start with the v2 signature; middleware mangling the first bytes of the stream.","solutions":["Ensure the upstream proxy is configured for PROXY protocol v2 binary output, not v1 text","Verify the sender actually prepends the 16-byte v2 signature+header before application data","Capture the first bytes from the client and confirm the ver/cmd byte is 0x20-0x2F","If you must accept v1, enable/expect v1 parsing instead of feeding v1 into the v2 path"],"exampleFix":"// before (proxy sending v1 text)\nPROXY TCP4 192.0.2.1 192.0.2.2 4242 443\n// after (HAProxy v2 binary)\nserver ... send-proxy-v2","handlingStrategy":"validation","validationCode":"// Verify the ver/cmd byte before sending: version nibble must be 0x2\nif hdr[12]&0xF0 != 0x20 {\n    return fmt.Errorf(\"not a PROXY v2 header: ver/cmd=0x%02x\", hdr[12])\n}","typeGuard":"func isProxyV2VerCmd(b byte) bool { return b&0xF0 == 0x20 }","tryCatchPattern":"addr, err := readProxyProtoHeader(conn)\nif err != nil {\n    if errors.Is(err, errProxyProtoInvalid) {\n        // reject/malformed client: log source IP and close\n        conn.Close()\n        return\n    }\n    return err\n}","preventionTips":["Configure load balancers for send-proxy-v2, never v1, when the server expects v2","Unit-test senders against the 16-byte v2 signature + 0x21 ver/cmd","Log the raw first bytes on parse failure to speed diagnosis","Keep one PROXY protocol version across the whole chain"],"tags":["proxy-protocol","network","binary-protocol"],"backgroundTag":"proxy-protocol-invalid-version","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}