XTLS/Xray-core · error

VLESS fallbacks: invalid PROXY protocol version, "xver" only

Error message

VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2

What it means

Thrown by VLessInboundConfig.Build() when a fallback's "xver" (PROXY protocol version) is greater than 2. Only 0 (disable), 1 (PROXY v1, text) and 2 (PROXY v2, binary) exist; any larger integer is meaningless and rejected. Note that negative values cannot occur because the field is an unsigned integer type.

Source

Thrown at infra/conf/vless.go:210

				if strings.HasPrefix(fb.Dest, "@@") && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
					fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
					copy(fullAddr, fb.Dest[1:])
					fb.Dest = string(fullAddr)
				}
			} else {
				if _, err := strconv.Atoi(fb.Dest); err == nil {
					fb.Dest = "localhost:" + fb.Dest
				}
				if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
					fb.Type = "tcp"
				}
			}
		}
		if fb.Type == "" {
			return nil, errors.New(`VLESS fallbacks: please fill in a valid value for every "dest"`)
		}
		if fb.Xver > 2 {
			return nil, errors.New(`VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`)
		}
	}

	return config, nil
}

type VLessReverseConfig struct {
	Tag      string          `json:"tag"`
	Sniffing *SniffingConfig `json:"sniffing"`
}

func (c *VLessReverseConfig) Build() (*vless.Reverse, error) {
	if c.Tag == "" {
		return nil, errors.New(`VLESS reverse: "tag" can't be empty`)
	}
	r := &vless.Reverse{
		Tag: c.Tag,
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set "xver" to 0, 1, or 2 — 1 or 2 if the fallback target understands PROXY protocol
  2. Set "xver": 0 if the backend (e.g. plain nginx without proxy_protocol) does not support it

Example fix

// before
"fallbacks": [{ "dest": 80, "xver": 3 }]
// after
"fallbacks": [{ "dest": 80, "xver": 1 }]
Defensive patterns

Strategy: validation

Validate before calling

func validateXver(fb map[string]any) error {
	if v, ok := fb["xver"]; ok {
		n, ok := v.(float64)
		if !ok || n != math.Trunc(n) || n < 0 || n > 2 {
			return fmt.Errorf("xver must be integer 0, 1, or 2, got %v", v)
		}
	}
	return nil
}

Type guard

func validXver(v any) bool {
	n, ok := v.(float64)
	return ok && n == math.Trunc(n) && n >= 0 && n <= 2
}

Prevention

When it happens

Trigger: "fallbacks":[{"dest":80,"xver":3}] or any xver > 2; typically from guessing that higher means newer/better, or from configs edited for a different proxy that supports xver 3+.

Common situations: Users copy xver from HAProxy docs (which discusses v2) and bump it; automated config generators emitting a default of 3; hand-edited JSON after an upgrade.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/4b39cb0e5b8aa285. Report an issue: GitHub.