juanfont/headscale · error · ErrProtocolOutOfRange

%w: %d

Error message

%w: %d

What it means

The proto string parsed as an integer but fell outside 0-255 (ErrProtocolOutOfRange). IP protocol numbers are a single byte, so anything larger (or negative via a leading '-') is invalid.

Source

Thrown at hscontrol/policy/v2/types.go:1779

	case ProtocolNameWildcard:
		// Wildcard "*" is not allowed - Tailscale rejects it
		return errUnknownProtocolWildcard
	default:
		// Try to parse as a numeric protocol number
		str := string(*p)

		// Check for leading zeros (not allowed by Tailscale)
		if str == "0" || (len(str) > 1 && str[0] == '0') {
			return fmt.Errorf("%w: %q", ErrProtocolLeadingZero, str)
		}

		protocolNumber, err := strconv.Atoi(str)
		if err != nil {
			return fmt.Errorf("%w: %q must be a known protocol name or valid protocol number 0-255", ErrInvalidProtocolNumber, *p)
		}

		if protocolNumber < 0 || protocolNumber > 255 {
			return fmt.Errorf("%w: %d", ErrProtocolOutOfRange, protocolNumber)
		}

		return nil
	}
}

// MarshalJSON implements JSON marshaling for [Protocol].
func (p *Protocol) MarshalJSON() ([]byte, error) {
	return json.Marshal(string(*p))
}

// Protocol constants matching the IANA numbers.
const (
	ProtocolICMP     = 1   // Internet Control Message
	ProtocolIGMP     = 2   // Internet Group Management
	ProtocolIPv4     = 4   // IPv4 encapsulation
	ProtocolTCP      = 6   // Transmission Control
	ProtocolEGP      = 8   // Exterior Gateway Protocol

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Correct the number to the intended IANA protocol (e.g. 6=tcp, 17=udp)
  2. If the value was meant to be a port, move it into the ports list

Example fix

// before
{"proto": "443", "ports": ["tcp"]}
// after
{"proto": "tcp", "ports": ["443"]}
Defensive patterns

Strategy: validation

Validate before calling

func protocolInRange(s string) bool {
	n, err := strconv.Atoi(s)
	return err == nil && n >= 0 && n <= 255
}

Prevention

When it happens

Trigger: A proto value like "256", "1000", or "-1" — often a port number accidentally placed in the proto field.

Common situations: Swapping the proto and port fields when hand-editing rules; confusing IANA protocol numbers with port numbers.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/f710b9a75413d0cc. Report an issue: GitHub.