{"record":{"id":"38bf58dc077b55f2","repo":"XTLS/Xray-core","slug":"trojan-fallbacks-please-fill-in-a-valid-value-for","errorCode":null,"errorMessage":"Trojan fallbacks: please fill in a valid value for every \"dest\"","messagePattern":"Trojan fallbacks: please fill in a valid value for every \"dest\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/trojan.go","lineNumber":197,"sourceCode":"\t\t\t\tfb.Type = \"serve\"\n\t\t\t} else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {\n\t\t\t\tfb.Type = \"unix\"\n\t\t\t\tif strings.HasPrefix(fb.Dest, \"@@\") && (runtime.GOOS == \"linux\" || runtime.GOOS == \"android\") {\n\t\t\t\t\tfullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy\n\t\t\t\t\tcopy(fullAddr, fb.Dest[1:])\n\t\t\t\t\tfb.Dest = string(fullAddr)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif _, err := strconv.Atoi(fb.Dest); err == nil {\n\t\t\t\t\tfb.Dest = \"localhost:\" + fb.Dest\n\t\t\t\t}\n\t\t\t\tif _, _, err := net.SplitHostPort(fb.Dest); err == nil {\n\t\t\t\t\tfb.Type = \"tcp\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif fb.Type == \"\" {\n\t\t\treturn nil, errors.New(`Trojan fallbacks: please fill in a valid value for every \"dest\"`)\n\t\t}\n\t\tif fb.Xver > 2 {\n\t\t\treturn nil, errors.New(`Trojan fallbacks: invalid PROXY protocol version, \"xver\" only accepts 0, 1, 2`)\n\t\t}\n\t}\n\n\treturn config, nil\n}\n","sourceCodeStart":179,"sourceCodeEnd":206,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/trojan.go#L179-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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\""],"exampleFix":"// before\n{ \"dest\": \"html/root\" }\n// after\n{ \"dest\": \"/var/www/html\" }   // absolute unix path, or { \"dest\": 80 } for a tcp port","handlingStrategy":"validation","validationCode":"func inferFallbackType(dest string) string {\n    if dest == \"serve-ws-none\" { return \"serve\" }\n    if filepath.IsAbs(dest) || strings.HasPrefix(dest, \"@\") { return \"unix\" }\n    if _, err := strconv.Atoi(dest); err == nil { return \"tcp\" }\n    if _, _, err := net.SplitHostPort(dest); err == nil { return \"tcp\" }\n    return \"\"\n}\n// reject before Xray sees it\nif inferFallbackType(dest) == \"\" && explicitType == \"\" {\n    return fmt.Errorf(\"fallback dest %q cannot be classified; give a port, host:port, absolute path, @socket, or set type\", dest)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer the documented canonical forms: port number, host:port, absolute unix path","Set \"type\" explicitly when dest is unusual"],"tags":["config","trojan","fallback","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}