{"record":{"id":"a6a1e06374f7b92f","repo":"XTLS/Xray-core","slug":"vless-users-tag-can-t-be-empty-for-reverse","errorCode":null,"errorMessage":"VLESS users: \"tag\" can't be empty for \"reverse\"","messagePattern":"VLESS users: \"tag\" can't be empty for \"reverse\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/vless.go","lineNumber":90,"sourceCode":"\t\tswitch account.Flow {\n\t\tcase \"\":\n\t\t\taccount.Flow = c.Flow\n\t\tcase vless.XRV:\n\t\tdefault:\n\t\t\treturn errors.New(`VLESS users: \"flow\" doesn't support \"` + account.Flow + `\" in this version`)\n\t\t}\n\n\t\tif len(account.Testseed) < 4 {\n\t\t\taccount.Testseed = c.Testseed\n\t\t}\n\n\t\tif account.Encryption != \"\" {\n\t\t\treturn errors.New(`VLESS users: \"encryption\" should not be in inbound settings`)\n\t\t}\n\n\t\tif account.Reverse != nil {\n\t\t\tif account.Reverse.Tag == \"\" {\n\t\t\t\treturn errors.New(`VLESS users: \"tag\" can't be empty for \"reverse\"`)\n\t\t\t}\n\t\t\tif account.Reverse.Sniffing != nil { // may not be reached: error json unmarshal\n\t\t\t\treturn errors.New(`VLESS users: inbound's \"reverse\" can't have \"sniffing\"`)\n\t\t\t}\n\t\t}\n\n\t\tuser.Account = serial.ToTypedMessage(account)\n\t\tconfig.Users[idx] = user\n\t\treturn nil\n\t}\n\n\tif err := task.ParallelForN(len(c.Users), processClient); err != nil {\n\t\treturn nil, err\n\t}\n\n\tconfig.Decryption = c.Decryption\n\tif !func() bool {\n\t\ts := strings.Split(config.Decryption, \".\")","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/vless.go#L72-L108","documentation":"A VLESS inbound user may declare a 'reverse' object (reverse proxy bridging), and if present its 'tag' must be non-empty — the tag is the routing identifier the reverse traffic is matched against. An empty tag makes the reverse entry unroutable, so the build fails.","triggerScenarios":"A clients entry with \"reverse\": { } or \"reverse\": { \"sniffing\": ... } but no \"tag\" value.","commonSituations":"Enabling the reverse feature on a user but forgetting to name the bridge tag, or a typo'd key like \"Tag\" that never binds to the tag field.","solutions":["Add a non-empty \"tag\" inside the reverse object, e.g. \"reverse\": { \"tag\": \"bridge\" }","Reference the same tag from the corresponding reverse outbound on the other end"],"exampleFix":"// before\n{ \"id\": \"8c1f...\", \"reverse\": {} }\n// after\n{ \"id\": \"8c1f...\", \"reverse\": { \"tag\": \"bridge\" } }","handlingStrategy":"validation","validationCode":"if r := gjson.Get(clientRaw, \"reverse\"); r.Exists() {\n    if gjson.Get(r.Raw, \"tag\").String() == \"\" {\n        return errors.New(\"reverse object requires a non-empty \\\"tag\\\"\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always name reverse tags (e.g. \"bridge\"/\"portal\") and reference them consistently","Use lowercase \"tag\" exactly"],"tags":["config","vless","reverse-proxy"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}