nats-io/nats-server · warning
failed to discard UNSPEC address address data: %w
Error message
failed to discard UNSPEC address address data: %w
What it means
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.
Source
Thrown at server/client_proxyproto.go:371
// Validate protocol (we only support STREAM/TCP)
if protocol != proxyProtoProtoStream {
return nil, fmt.Errorf("%w: only STREAM protocol supported", errProxyProtoUnsupported)
}
// 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)View on GitHub (pinned to 3a66a489d2)
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
Example fix
// before: UNSPEC header claiming 16 bytes, then close write(sig+header); conn.Close() // after: either addrLen=0 or write the full 16 payload bytes header addrLen=0x0000; write(sig+header)
Defensive patterns
Strategy: try-catch
Try / catch
addr, err := readProxyProtoHeader(conn)
if err != nil && strings.Contains(err.Error(), "failed to discard UNSPEC address address data") {
if errors.Is(err, io.ErrUnexpectedEOF) {
return errRetryable // sender truncated the payload
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Truncated headers from buggy or restarted proxies; health-check style senders using UNSPEC with a nonzero length then disconnecting; flaky network dropping mid-payload.
Related errors
- failed to read v2 signature: %w
- failed to read v2 header: %w
- failed to read PROXY protocol header: %w
- failed to discard LOCAL command address data: %w
- failed to read IPv4 address data: %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/5918bae9f625f12c.
Report an issue: GitHub.