tailscale/tailscale · error
port ranges for ProxyClass %q clash with existing ProxyClass
Error message
port ranges for ProxyClass %q clash with existing ProxyClass %q
What it means
Raised in validateNodePortRanges when one of this ProxyClass's NodePort ranges overlaps a range declared by a different existing ProxyClass. NodePorts are cluster-wide, so two ProxyClasses cannot share them; the spec is rejected as invalid.
Source
Thrown at k8s-operator/reconciler/proxyclass/proxyclass.go:448
if !r.IsValid() {
return fmt.Errorf("port range %q is invalid", r.String())
}
}
// TODO(ChaosInTheCRD): if a ProxyClass that made another invalid (due to port range clash) is deleted,
// the invalid ProxyClass doesn't get reconciled on, and therefore will not go valid. We should fix this.
proxyClassRanges, err := getPortsForProxyClasses(ctx, c)
if err != nil {
return fmt.Errorf("failed to get port ranges for ProxyClasses: %w", err)
}
for _, r := range portRanges {
for pcName, pcr := range proxyClassRanges {
if pcName == pc.Name {
continue
}
if pcr.ClashesWith(r) {
return fmt.Errorf("port ranges for ProxyClass %q clash with existing ProxyClass %q", pc.Name, pcName)
}
}
}
if len(portRanges) == 1 {
return nil
}
sort.Slice(portRanges, func(i, j int) bool {
return portRanges[i].Port < portRanges[j].Port
})
for i := 1; i < len(portRanges); i++ {
prev := portRanges[i-1]
curr := portRanges[i]
if curr.Port <= prev.Port || curr.Port <= prev.EndPort {
return fmt.Errorf("overlapping ranges: %q and %q", prev.String(), curr.String())
}View on GitHub (pinned to 6e0912f979)
Solutions
- The ProxyClass port range clashes with an existing ProxyClass; choose a non-overlapping port range.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at k8s-operator/reconciler/proxyclass/proxyclass.go:448 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/067823c2f8f50ac1.
Report an issue: GitHub.