{"record":{"id":"5918bae9f625f12c","repo":"nats-io/nats-server","slug":"failed-to-discard-unspec-address-address-data-w","errorCode":null,"errorMessage":"failed to discard UNSPEC address address data: %w","messagePattern":"failed to discard UNSPEC address address data: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/client_proxyproto.go","lineNumber":371,"sourceCode":"\t// Validate protocol (we only support STREAM/TCP)\n\tif protocol != proxyProtoProtoStream {\n\t\treturn nil, fmt.Errorf(\"%w: only STREAM protocol supported\", errProxyProtoUnsupported)\n\t}\n\n\t// Parse address data based on family\n\tvar addr *proxyProtoAddr\n\tvar err error\n\tswitch family {\n\tcase proxyProtoFamilyInet:\n\t\taddr, err = parseIPv4Addr(conn, addrLen)\n\tcase proxyProtoFamilyInet6:\n\t\taddr, err = parseIPv6Addr(conn, addrLen)\n\tcase proxyProtoFamilyUnspec:\n\t\t// UNSPEC family with PROXY command is valid but rare\n\t\t// Just skip the address data\n\t\tif addrLen > 0 {\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 UNSPEC address address data: %w\", err)\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"%w: unsupported address family 0x%02x\", errProxyProtoUnsupported, family)\n\t}\n\treturn addr, err\n}\n\n// parseIPv4Addr parses IPv4 address data from PROXY protocol header\nfunc parseIPv4Addr(conn net.Conn, addrLen uint16) (*proxyProtoAddr, error) {\n\t// IPv4: 4 (src IP) + 4 (dst IP) + 2 (src port) + 2 (dst port) = 12 bytes minimum\n\tif addrLen < proxyProtoAddrSizeIPv4 {\n\t\treturn nil, fmt.Errorf(\"IPv4 address data too short: %d bytes\", addrLen)\n\t}\n\taddrData := make([]byte, addrLen)\n\tif _, err := io.ReadFull(conn, addrData); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read IPv4 address data: %w\", err)","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L353-L389","documentation":"When family is UNSPEC (0x0) with a PROXY command, the address payload carries no usable address, so the library simply discards addrLen bytes from the connection and returns nil. This error wraps any I/O failure while discarding those bytes — usually the peer closing or timing out before all advertised bytes arrive.","triggerScenarios":"Peer declares UNSPEC family with addrLen>0 but delivers fewer bytes than advertised, or the connection hits the read deadline / EOF / reset while io.CopyN drains the payload.","commonSituations":"Truncated headers from buggy or restarted proxies; health-check style senders using UNSPEC with a nonzero length then disconnecting; flaky network dropping mid-payload.","solutions":["Inspect the wrapped error: unexpected EOF indicates the sender advertised more bytes than it sent","Fix the sender to set addrLen=0 for UNSPEC family, or send the full advertised payload","Retry the connection if transient (deadline exceeded / connection reset)","Bump the read deadline if the sender is merely slow"],"exampleFix":"// before: UNSPEC header claiming 16 bytes, then close\nwrite(sig+header); conn.Close()\n// after: either addrLen=0 or write the full 16 payload bytes\nheader addrLen=0x0000; write(sig+header)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"addr, err := readProxyProtoHeader(conn)\nif err != nil && strings.Contains(err.Error(), \"failed to discard UNSPEC address address data\") {\n    if errors.Is(err, io.ErrUnexpectedEOF) {\n        return errRetryable // sender truncated the payload\n    }\n    return err\n}","preventionTips":["Senders should set addrLen=0 for UNSPEC family instead of advertising unused bytes","Always write the complete advertised payload before any further sends or close","Use generous read deadlines for low-bandwidth health-check senders","Alert on unexpected EOF rates to catch misbehaving proxies early"],"tags":["proxy-protocol","network","io"],"backgroundTag":"proxy-protocol-truncated-header","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}