nats-io/nats-server · warning

failed to read IPv6 address data: %w

Error message

failed to read IPv6 address data: %w

What it means

The AF_INET6 header declared a valid (>=36 byte) address length, but io.ReadFull could not read that many bytes from the connection, so the IPv6 address payload arrived incomplete. The wrapped underlying I/O error is preserved via %w.

Source

Thrown at server/client_proxyproto.go:407

		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)
	}
	addrData := make([]byte, addrLen)
	if _, err := io.ReadFull(conn, addrData); err != nil {
		return nil, fmt.Errorf("failed to read IPv6 address data: %w", err)
	}
	return &proxyProtoAddr{
		srcIP:   net.IP(addrData[0:16]),
		dstIP:   net.IP(addrData[16:32]),
		srcPort: binary.BigEndian.Uint16(addrData[32:34]),
		dstPort: binary.BigEndian.Uint16(addrData[34:36]),
	}, nil
}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Have the proxy send the whole PROXY v2 header in one write to reduce the partial-read window.
  2. Treat as transient: reconnect; inspect the wrapped error with errors.Is(err, io.ErrUnexpectedEOF) vs timeout to decide.
  3. Verify nothing between LB and server (idle timeouts, security appliances) is cutting short connections immediately after header write.
Defensive patterns

Strategy: retry

Type guard

func isHeaderTruncation(err error) bool {
    return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, net.ErrClosed)
}

Try / catch

if err != nil {
    var terr net.Error
    if errors.As(err, &terr) && terr.Timeout() {
        return retryWithBackoff()
    }
    if strings.Contains(err.Error(), "failed to read IPv6 address data") {
        return reconnect() // peer dropped mid-header
    }
}

Prevention

When it happens

Trigger: Connection closed or timed out after the v2 header was partially written; the peer sent only the 16-byte signature + length and then dropped; scanner/probe sent a truncated header.

Common situations: Health checks against a PROXY listener; unstable networks between LB and NATS; proxies split writes across packets and the client disconnects between them.

Related errors


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