nats-io/nats-server · error

%w: unsupported address family 0x%02x

Error message

%w: unsupported address family 0x%02x

What it means

During PROXY protocol v2 header parsing, the address family byte in the header was neither AF_INET (0x11), AF_INET6 (0x21), nor the UNSPEC (0x00) case handled earlier. The server rejects the connection because it cannot interpret the address payload that follows. The error is wrapped with errProxyProtoUnsupported so callers can test for the unsupported family class with errors.Is.

Source

Thrown at server/client_proxyproto.go:376

	// Parse address data based on family
	var addr *proxyProtoAddr
	var err error
	switch family {
	case proxyProtoFamilyInet:
		addr, err = parseIPv4Addr(conn, addrLen)
	case proxyProtoFamilyInet6:
		addr, err = parseIPv6Addr(conn, addrLen)
	case proxyProtoFamilyUnspec:
		// 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]),

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Fix the upstream proxy/load balancer to emit a standard INET (0x11) or INET6 (0x21) v2 header, or disable PROXY protocol on the listener if the peer does not actually speak it.
  2. If you need UNIX-socket family support, patch parseProxyProtoV2Header in server/client_proxyproto.go to handle that family, or pre-normalize headers at the proxy.
  3. Catch the error with errors.Is(err, errProxyProtoUnsupported) and drop/close the connection rather than retrying, since the peer header is malformed.

Example fix

// before: connection through lb fails
// haproxy config sends raw v2 with unix family
// after
defaults
  mode tcp
  option proxy-protocol-v2  # emit standard INET family
server s1 127.0.0.1:4222 send-proxy-v2
Defensive patterns

Strategy: fallback

Validate before calling

if len(hdr) >= 15 && hdr[13] == 0x20 {
    fam := hdr[14]
    if fam != 0x00 && fam != 0x11 && fam != 0x21 {
        return fmt.Errorf("pre-check: unsupported proxy v2 family 0x%02x", fam)
    }
}

Type guard

func isSupportedV2Family(family byte) bool {
    return family == 0x00 || family == 0x11 || family == 0x21
}

Try / catch

addr, err := readProxyProtoHeader(conn)
if errors.Is(err, errProxyProtoUnsupported) {
    conn.Close() // malformed peer; do not retry
    return
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: A client connects through a PROXY-enabled listener and sends a v2 PROXY header whose address family/protocol byte (byte 14 of the header) is an undefined value, e.g. a corrupt or malicious header, or a sender claiming a protocol combination like UNIX stream (0x20/0x31) that this parser does not implement.

Common situations: Misconfigured load balancers emitting UNIX-socket or datagram family PROXY v2 headers; fuzzing or probes sending garbage after the 12-byte signature; protocol mismatches where a v1 header is misdetected as v2.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/00429a21df586326. Report an issue: GitHub.