nats-io/nats-server · error
IPv4 address data too short: %d bytes
Error message
IPv4 address data too short: %d bytes
What it means
parseIPv4Addr requires at least proxyProtoAddrSizeIPv4 (12) bytes of address data for an AF_INET PROXY v2 header (4 src IP + 4 dst IP + 2 src port + 2 dst port). The declared addrLen from the header was smaller, so the payload cannot possibly contain a valid IPv4 endpoint pair and parsing is aborted immediately without reading from the connection.
Source
Thrown at server/client_proxyproto.go:385
// UNSPEC family with PROXY command is valid but rare
// Just skip the address data
if addrLen > 0 {
if _, err := io.CopyN(io.Discard, conn, int64(addrLen)); err != nil {
return nil, fmt.Errorf("failed to discard UNSPEC address address data: %w", err)
}
}
return nil, nil
default:
return nil, fmt.Errorf("%w: unsupported address family 0x%02x", errProxyProtoUnsupported, family)
}
return addr, err
}
// parseIPv4Addr parses IPv4 address data from PROXY protocol header
func parseIPv4Addr(conn net.Conn, addrLen uint16) (*proxyProtoAddr, error) {
// IPv4: 4 (src IP) + 4 (dst IP) + 2 (src port) + 2 (dst port) = 12 bytes minimum
if addrLen < proxyProtoAddrSizeIPv4 {
return nil, fmt.Errorf("IPv4 address data too short: %d bytes", addrLen)
}
addrData := make([]byte, addrLen)
if _, err := io.ReadFull(conn, addrData); err != nil {
return nil, fmt.Errorf("failed to read IPv4 address data: %w", err)
}
return &proxyProtoAddr{
srcIP: net.IP(addrData[0:4]),
dstIP: net.IP(addrData[4:8]),
srcPort: binary.BigEndian.Uint16(addrData[8:10]),
dstPort: binary.BigEndian.Uint16(addrData[10:12]),
}, nil
}
// parseIPv6Addr parses IPv6 address data from PROXY protocol header
func parseIPv6Addr(conn net.Conn, addrLen uint16) (*proxyProtoAddr, error) {
// IPv6: 16 (src IP) + 16 (dst IP) + 2 (src port) + 2 (dst port) = 36 bytes minimum
if addrLen < proxyProtoAddrSizeIPv6 {
return nil, fmt.Errorf("IPv6 address data too short: %d bytes", addrLen)View on GitHub (pinned to 3a66a489d2)
Solutions
- Fix the proxy to always declare 12 bytes for AF_INET (or 36 for AF_INET6) in the length field of the v2 header.
- Update/replace the middleware emitting PROXY v2 headers if it is a home-grown implementation.
- If you control the connecting client, switch it to PROXY v1 or plain TCP, since this server validates lengths strictly.
Example fix
// before: custom proxy writes only the two IPs lenBuf := make([]byte, 2) binary.BigEndian.PutUint16(lenBuf, 8) // after: include ports (12 bytes for IPv4) binary.BigEndian.PutUint16(lenBuf, 12)
Defensive patterns
Strategy: validation
Validate before calling
// pre-validate before sending a v2 header
canonical := map[byte]uint16{0x11: 12, 0x21: 36}
if want, ok := canonical[hdr[14]]; !ok || addrLen < want {
return fmt.Errorf("addrLen %d too small for family 0x%02x", addrLen, hdr[14])
} Type guard
func validIPv4AddrLen(n uint16) bool { return n >= 12 } Prevention
- Test your proxy header writer against haproxy's PROXY v2 spec (12/36/216-byte lengths)
- Never hardcode IPv4 lengths when the upstream address family can be IPv6
- Add integration tests that round-trip v2 headers through your proxy
When it happens
Trigger: A v2 PROXY header with command/family byte 0x11 but an address-length field less than 12 bytes, e.g. a truncated or hand-crafted header, or a sender that set the length to the IP-only size (8) and forgot the ports.
Common situations: Custom or buggy proxy implementations writing the wrong length field; packets truncated by MTU/fragmentation bugs; fuzz traffic; header corruption from TCP interception.
Related errors
- %w: unsupported address family 0x%02x
- IPv6 address data too short: %d bytes
- got corrupted escaped character
- incomplete type, value pair
- DN ended with incomplete type, value pair
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/1505dee0c5774cf5.
Report an issue: GitHub.