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
- 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"
- Or set "type" explicitly (e.g. "tcp", "unix", "serve") alongside dest
- 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
- Prefer the documented canonical forms: port number, host:port, absolute unix path
- Set "type" explicitly when dest is unusual
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
- Trojan server address is not set.
- Invalid Trojan port.
- Trojan password is not specified.
- Trojan fallbacks: "path" must be empty or start with "/"
- Trojan fallbacks: invalid PROXY protocol version, "xver" onl
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/38bf58dc077b55f2.
Report an issue: GitHub.