{"record":{"id":"4dd20af6f9e47133","repo":"XTLS/Xray-core","slug":"vless-fallbacks-path-must-be-empty-or-start-wit","errorCode":null,"errorMessage":"VLESS fallbacks: \"path\" must be empty or start with \"/\"","messagePattern":"VLESS fallbacks: \"path\" must be empty or start with \"/\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/vless.go","lineNumber":185,"sourceCode":"\t\t\t_ = json.Unmarshal(fb.Dest, &s)\n\t\t}\n\t\tconfig.Fallbacks = append(config.Fallbacks, &inbound.Fallback{\n\t\t\tName: fb.Name,\n\t\t\tAlpn: fb.Alpn,\n\t\t\tPath: fb.Path,\n\t\t\tType: fb.Type,\n\t\t\tDest: s,\n\t\t\tXver: fb.Xver,\n\t\t})\n\t}\n\tfor _, fb := range config.Fallbacks {\n\t\t/*\n\t\t\tif fb.Alpn == \"h2\" && fb.Path != \"\" {\n\t\t\t\treturn nil, errors.New(`VLESS fallbacks: \"alpn\":\"h2\" doesn't support \"path\"`)\n\t\t\t}\n\t\t*/\n\t\tif fb.Path != \"\" && fb.Path[0] != '/' {\n\t\t\treturn nil, errors.New(`VLESS fallbacks: \"path\" must be empty or start with \"/\"`)\n\t\t}\n\t\tif fb.Type == \"\" && fb.Dest != \"\" {\n\t\t\tif fb.Dest == \"serve-ws-none\" {\n\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}","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/vless.go#L167-L203","documentation":"Thrown by VLessInboundConfig.Build() when validating fallbacks for a VLESS inbound. Each fallback's optional \"path\" field must either be empty or begin with '/', because the path is matched against the URL path of the incoming HTTP request, which always starts with '/'. Any other value (e.g. \"ws\", \"path=/ws\") cannot match and is rejected at config-build time.","triggerScenarios":"Config with \"fallbacks\":[{\"dest\":\"80\",\"path\":\"ws\"}] — path set without a leading slash. Also happens when users copy a WebSocket \"path\" value from a transport settings block (where no slash is required) into the fallback object.","commonSituations":"Migrating a config from websocket transport to fallbacks; mixing up transport \"path\" and fallback \"path\" semantics; typos like \"path\":\"//ws\" or \"path\":\"=\" prefix from proxy-share link generators.","solutions":["Change the fallback path to start with '/', e.g. \"path\":\"/ws\"","Remove \"path\" entirely if the fallback should catch all paths","Double-check you are editing the fallbacks array, not the streamSettings wsSettings"],"exampleFix":"// before\n\"fallbacks\": [{ \"dest\": 80, \"path\": \"ws\" }]\n// after\n\"fallbacks\": [{ \"dest\": 80, \"path\": \"/ws\" }]","handlingStrategy":"validation","validationCode":"func validateFallbackPaths(cfg map[string]any) error {\n\tinbounds, _ := cfg[\"inbounds\"].([]any)\n\tfor _, ib := range inbounds {\n\t\tm, _ := ib.(map[string]any)\n\t\tsettings, _ := m[\"settings\"].(map[string]any)\n\t\tfbs, _ := settings[\"fallbacks\"].([]any)\n\t\tfor _, f := range fbs {\n\t\t\tfb, _ := f.(map[string]any)\n\t\t\tif p, ok := fb[\"path\"].(string); ok && p != \"\" && !strings.HasPrefix(p, \"/\") {\n\t\t\t\treturn fmt.Errorf(\"fallback path %q must be empty or start with /\", p)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func validFallbackPath(p any) bool {\n\ts, ok := p.(string)\n\treturn !ok || s == \"\" || strings.HasPrefix(s, \"/\")\n}","tryCatchPattern":null,"preventionTips":["Treat fallback paths as URL paths: always begin with '/'","Never copy wsSettings.path values verbatim into fallbacks without adding the slash","Add a config-lint step (jq script or Go validator) to CI for generated configs"],"tags":["vless","config","fallbacks","validation","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}