{"record":{"id":"d67f7b5cf3ae737b","repo":"nats-io/nats-server","slug":"unsupported-proxy-protocol-version-d","errorCode":null,"errorMessage":"unsupported PROXY protocol version: %d","messagePattern":"unsupported PROXY protocol version: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/client_proxyproto.go","lineNumber":282,"sourceCode":"\t\t}\n\n\t\t// Verify full signature\n\t\tfullSig := string(firstBytes) + string(remaining)\n\t\tif fullSig != proxyProtoV2Sig {\n\t\t\treturn nil, nil, fmt.Errorf(\"%w: invalid signature\", errProxyProtoInvalid)\n\t\t}\n\n\t\t// Read rest of header: ver/cmd, fam/proto, addr-len (4 bytes)\n\t\theader := make([]byte, 4)\n\t\tif _, err := io.ReadFull(conn, header); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to read v2 header: %w\", err)\n\t\t}\n\n\t\t// Continue with parsing\n\t\taddr, err := parseProxyProtoV2Header(conn, header)\n\t\treturn addr, nil, err\n\tdefault:\n\t\treturn nil, nil, fmt.Errorf(\"unsupported PROXY protocol version: %d\", version)\n\t}\n}\n\n// readProxyProtoV2Header is kept for backward compatibility and direct testing.\n// It reads and parses a PROXY protocol v2 header from the connection.\n// If the command is LOCAL (health check), it returns nil for addr and no error.\n// If the command is PROXY, it returns the parsed address information.\n// The connection must be fresh (no data read yet).\nfunc readProxyProtoV2Header(conn net.Conn) (*proxyProtoAddr, error) {\n\t// Set read deadline to prevent hanging on slow/malicious clients\n\tif err := conn.SetReadDeadline(time.Now().Add(proxyProtoReadTimeout)); err != nil {\n\t\treturn nil, err\n\t}\n\tdefer conn.SetReadDeadline(time.Time{})\n\n\t// Read fixed header (16 bytes)\n\theader := make([]byte, proxyProtoV2HeaderSize)\n\tif _, err := io.ReadFull(conn, header); err != nil {","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L264-L300","documentation":"This error is returned from the default branch of readProxyProtoHeader's version switch when detectProxyProtoVersion reports a version that is neither 1 nor 2. In the current implementation detectProxyProtoVersion only returns 1, 2, or an error, so this branch is a defensive guard for future/unknown protocol versions rather than a code path reachable through the public detection logic. It formats the detected version number into the message for diagnostics.","triggerScenarios":"Only reachable if detectProxyProtoVersion is changed or extended to return a version other than 1 or 2 without readProxyProtoHeader being updated; the corresponding test (TestClientProxyProtoV1ParseUnknown et al.) exercises the surrounding switch but this branch itself would require a hypothetical version like 3.","commonSituations":"Future PROXY protocol revisions or custom forks emitting a new version byte; custom modifications to detectProxyProtoVersion; third-party code vendoring the parser and adding a version case upstream.","solutions":["Confirm the sender's PROXY protocol version; only v1 (text 'PROXY ...') and v2 (binary signature) are supported by this parser.","If you modified detectProxyProtoVersion, add a corresponding case to the switch in readProxyProtoHeader or map the new version onto the existing v1/v2 parsers.","Upstream: this is defensive code; if you see it in production without local modifications, capture the connection bytes and report the sender's protocol output."],"exampleFix":"// before: detectProxyProtoVersion returns 3 for an experimental format\n// after: return errProxyProtoUnrecognized for unknown versions so the\n// unrecognized-format path (with byte replay) handles it instead\n// if sig is neither v1 prefix nor v2 sig prefix { return 0, header, errProxyProtoUnrecognized }","handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isUnsupportedVersion(err error) bool {\n\treturn err != nil && strings.HasPrefix(err.Error(), \"unsupported PROXY protocol version:\")\n}","tryCatchPattern":"addr, extra, err := readProxyProtoHeader(conn)\nif err != nil {\n\tif isUnsupportedVersion(err) {\n\t\t// log version number from message; fall back to non-PROXY handling or reject\n\t\tconn.Close()\n\t\treturn\n\t}\n\treturn\n}","preventionTips":["Only v1 and v2 exist in practice; keep senders on standard PROXY protocol versions.","If you extend detectProxyProtoVersion, update the switch in readProxyProtoHeader in the same change.","Prefer returning errProxyProtoUnrecognized from detection so unknown formats hit the replay-capable path.","Add a unit test covering the default branch whenever the version detection logic changes."],"tags":["proxy-protocol","versioning","defensive-guard"],"backgroundTag":"unsupported-protocol-version","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}