nats-io/nats-server · warning

failed to discard LOCAL command address data: %w

Error message

failed to discard LOCAL command address data: %w

What it means

After a LOCAL command (health check) is parsed, the library must still consume addrLen bytes of address payload from the connection so the stream stays in sync. This error wraps whatever failure occurred while discarding those bytes (io.CopyN error, usually EOF/timeout/reset).

Source

Thrown at server/client_proxyproto.go:342

	if version != proxyProtoV2Ver {
		return nil, fmt.Errorf("%w: invalid version 0x%02x", errProxyProtoInvalid, version)
	}

	// Parse address family and protocol
	famProto := header[1]
	family := famProto & proxyProtoFamilyMask
	protocol := famProto & proxyProtoProtoMask

	// Parse address length (big-endian uint16)
	addrLen := binary.BigEndian.Uint16(header[2:4])

	// Handle LOCAL command (health check)
	if command == proxyProtoCmdLocal {
		// For LOCAL, we should skip the address data if any
		if addrLen > 0 {
			// Discard the address data
			if _, err := io.CopyN(io.Discard, conn, int64(addrLen)); err != nil {
				return nil, fmt.Errorf("failed to discard LOCAL command address data: %w", err)
			}
		}
		return nil, nil // nil addr indicates LOCAL command
	}

	// Handle PROXY command
	if command != proxyProtoCmdProxy {
		return nil, fmt.Errorf("unknown PROXY protocol command: 0x%02x", command)
	}

	// 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

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Check the wrapped error: EOF/unexpected EOF means the sender truncated the header payload
  2. Ensure health-check senders transmit the full address section matching the declared length
  3. Increase the read deadline if the sender is slow rather than broken
  4. Retry the connection — this is typically transient on flaky networks

Example fix

// before: sender sends LOCAL header claiming 12 bytes but closes early
conn.Close()
// after: send the full advertised payload
write(header); write(addrBytes) // addrBytes len == addrLen
Defensive patterns

Strategy: try-catch

Try / catch

addr, err := readProxyProtoHeader(conn)
if err != nil && strings.Contains(err.Error(), "failed to discard LOCAL command address data") {
    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(context.DeadlineExceeded, err) {
        return errRetryable
    }
    return err
}

Prevention

When it happens

Trigger: Peer sends a v2 header declaring command LOCAL with addrLen>0 but closes, times out (proxyProtoReadDeadline), or resets the connection before the declared address bytes can be read; or sends fewer bytes than advertised in the length field.

Common situations: Health checker abruptly closing after sending a LOCAL header; a truncated packet from a buggy proxy; network drop mid-header; aggressive client timeouts.

Related errors


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