XTLS/Xray-core · error

VLESS fallbacks: please fill in a valid value for every "des

Error message

VLESS fallbacks: please fill in a valid value for every "dest"

What it means

Thrown by VLessInboundConfig.Build() when a fallback's "type" could not be inferred. If "type" is not set explicitly, the builder tries to derive it from "dest": "serve-ws-none" becomes "serve", an absolute filesystem path or a '@'-prefixed string becomes "unix", a pure number becomes "localhost:<port>", and any valid host:port becomes "tcp". If none of these match (e.g. dest is empty, or is a relative string like "mysite.com:80" that fails SplitHostPort parsing), Type stays empty and this error is returned.

Source

Thrown at infra/conf/vless.go:207

				fb.Type = "serve"
			} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
				fb.Type = "unix"
				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`)
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set "dest" to a valid "host:port" (e.g. "localhost:80") or a bare port number (e.g. 80)
  2. Or set "type" explicitly to "tcp"/"unix"/"serve" alongside the dest
  3. For Unix sockets use an absolute path ("/path/sock") or '@'-prefixed abstract socket
  4. Remove URLs/schemes from dest — only raw addresses are accepted

Example fix

// before
"fallbacks": [{ "path": "/ws" }]
// after
"fallbacks": [{ "dest": "localhost:80", "path": "/ws" }]
Defensive patterns

Strategy: validation

Validate before calling

func validateFallbackDest(fb map[string]any) error {
	if t, _ := fb["type"].(string); t != "" {
		return nil
	}
	dest, _ := fb["dest"].(string)
	if dest == "serve-ws-none" || strings.HasPrefix(dest, "@") {
		return nil
	}
	if filepath.IsAbs(dest) {
		return nil
	}
	if _, err := strconv.Atoi(dest); err == nil {
		return nil
	}
	if _, _, err := net.SplitHostPort(dest); err == nil {
		return nil
	}
	return fmt.Errorf("fallback dest %q cannot be typed; set dest to host:port, a port number, an absolute path, @sock, or set type explicitly", dest)
}

Type guard

func fallbackDestValid(dest string) bool {
	if dest == "" { return false }
	if dest == "serve-ws-none" || strings.HasPrefix(dest, "@") || filepath.IsAbs(dest) { return true }
	if _, err := strconv.Atoi(dest); err == nil { return true }
	_, _, err := net.SplitHostPort(dest)
	return err == nil
}

Prevention

When it happens

Trigger: "fallbacks":[{}] with no dest at all; dest like "example.com 80" (space instead of colon); dest "/var/run/x" on Windows where filepath.IsAbs is false; dest "8080:" or other malformed host:port that net.SplitHostPort rejects.

Common situations: Minimal fallback configs that omit dest; copy-paste from examples with placeholders; OS-dependent absolute-path behavior (Unix paths on Windows); dest with brackets/schemes like "http://localhost:80".

Related errors


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