XTLS/Xray-core · error

Trojan fallbacks: please fill in a valid value for every "de

Error message

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

What it means

Thrown when a Trojan fallback's 'type' cannot be inferred from its 'dest'. Type inference: pure number → localhost port; absolute path or '@'-prefixed → unix socket (with '@@' abstract-socket handling on Linux); host:port → tcp; the literal "serve-ws-none" → serve. If dest matches none of these and no explicit "type" was given, fb.Type stays empty and this error fires.

Source

Thrown at infra/conf/trojan.go:197

				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(`Trojan fallbacks: please fill in a valid value for every "dest"`)
		}
		if fb.Xver > 2 {
			return nil, errors.New(`Trojan fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`)
		}
	}

	return config, nil
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Use a recognized dest form: a port number (80), "localhost:8080" style host:port, an absolute unix path ("/var/run/x.sock"), or "@abstract-socket"
  2. Or set "type" explicitly (e.g. "tcp", "unix", "serve") alongside dest
  3. For a catch-all WebSocket fallback, use "dest": "serve-ws-none"

Example fix

// before
{ "dest": "html/root" }
// after
{ "dest": "/var/www/html" }   // absolute unix path, or { "dest": 80 } for a tcp port
Defensive patterns

Strategy: validation

Validate before calling

func inferFallbackType(dest string) string {
    if dest == "serve-ws-none" { return "serve" }
    if filepath.IsAbs(dest) || strings.HasPrefix(dest, "@") { return "unix" }
    if _, err := strconv.Atoi(dest); err == nil { return "tcp" }
    if _, _, err := net.SplitHostPort(dest); err == nil { return "tcp" }
    return ""
}
// reject before Xray sees it
if inferFallbackType(dest) == "" && explicitType == "" {
    return fmt.Errorf("fallback dest %q cannot be classified; give a port, host:port, absolute path, @socket, or set type", dest)
}

Prevention

When it happens

Trigger: A fallback like { "dest": "example.com:80" } that is a valid host:port would pass, but { "dest": "web" } (bare name without port), { "dest": "" } or a relative path like "web/root" with no type fails.

Common situations: Using a relative filesystem path instead of an absolute one, a domain without a port, or an empty dest when the intent was 'catch-all' — for catch-all use "serve-ws-none" or set an explicit type.

Related errors


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