{"record":{"id":"dcb12e9c3895a657","repo":"XTLS/Xray-core","slug":"vmess-vnext-users-should-have-one-and-only-one","errorCode":null,"errorMessage":"VMess vnext: \"users\" should have one and only one member. Multiple members in \"users\" should use multiple VMess outbounds and routing balancer instead","messagePattern":"VMess vnext: \"users\" should have one and only one member\\. Multiple members in \"users\" should use multiple VMess outbounds and routing balancer instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/vmess.go","lineNumber":141,"sourceCode":"func (c *VMessOutboundConfig) Build() (proto.Message, error) {\n\terrors.PrintNonRemovalDeprecatedFeatureWarning(\"VMess (with no Forward Secrecy, etc.)\", \"VLESS Encryption\")\n\n\tconfig := new(outbound.Config)\n\tif c.Address != nil {\n\t\tc.Receivers = []*VMessOutboundTarget{\n\t\t\t{\n\t\t\t\tAddress: c.Address,\n\t\t\t\tPort:    c.Port,\n\t\t\t\tUsers:   []json.RawMessage{{}},\n\t\t\t},\n\t\t}\n\t}\n\tif len(c.Receivers) != 1 {\n\t\treturn nil, errors.New(`VMess settings: \"vnext\" should have one and only one member. Multiple endpoints in \"vnext\" should use multiple VMess outbounds and routing balancer instead`)\n\t}\n\tfor _, rec := range c.Receivers {\n\t\tif len(rec.Users) != 1 {\n\t\t\treturn nil, errors.New(`VMess vnext: \"users\" should have one and only one member. Multiple members in \"users\" should use multiple VMess outbounds and routing balancer instead`)\n\t\t}\n\t\tif rec.Address == nil {\n\t\t\treturn nil, errors.New(`VMess vnext: \"address\" is not set`)\n\t\t}\n\t\tspec := &protocol.ServerEndpoint{\n\t\t\tAddress: rec.Address.Build(),\n\t\t\tPort:    uint32(rec.Port),\n\t\t}\n\t\tfor _, rawUser := range rec.Users {\n\t\t\tuser := new(protocol.User)\n\t\t\tif c.Address != nil {\n\t\t\t\tuser.Level = c.Level\n\t\t\t\tuser.Email = c.Email\n\t\t\t} else {\n\t\t\t\tif err := json.Unmarshal(rawUser, user); err != nil {\n\t\t\t\t\treturn nil, errors.New(\"invalid VMess user\").Base(err)\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/vmess.go#L123-L159","documentation":"Thrown by VMessOutboundConfig.Build() when vnext[].users does not contain exactly one member. Each VMess outbound authenticates as a single user; multiple credentials require separate outbounds (optionally behind a balancer), and an empty users array is likewise invalid.","triggerScenarios":"\"vnext\":[{\"address\":\"a.com\",\"port\":443,\"users\":[]}]; users containing two credential objects; inbound-style clients arrays pasted into the outbound.","commonSituations":"Copying the server-side clients list into the outbound; removing a user while editing and leaving []; misunderstanding the one-identity-per-outbound rule.","solutions":["Keep exactly one user object: {\"id\":\"uuid\",\"alterId\":0,\"security\":\"auto\"}","Split multiple identities into multiple outbounds and balance via routing","Never leave \"users\" empty in an outbound vnext entry"],"exampleFix":"// before\n\"users\": [ {\"id\":\"uuid-a\"}, {\"id\":\"uuid-b\"} ]\n// after\n\"users\": [ {\"id\":\"uuid-a\", \"alterId\": 0, \"security\": \"auto\"} ]","handlingStrategy":"validation","validationCode":"func validateVMessSingleUser(cfg map[string]any) error {\n\toutbounds, _ := cfg[\"outbounds\"].([]any)\n\tfor _, ob := range outbounds {\n\t\tm, _ := ob.(map[string]any)\n\t\tif p, _ := m[\"protocol\"].(string); p != \"vmess\" { continue }\n\t\tsettings, _ := m[\"settings\"].(map[string]any)\n\t\tvnext, _ := settings[\"vnext\"].([]any)\n\t\tfor _, v := range vnext {\n\t\t\tep, _ := v.(map[string]any)\n\t\t\tusers, _ := ep[\"users\"].([]any)\n\t\t\tif len(users) != 1 {\n\t\t\t\treturn fmt.Errorf(\"outbound %v: vmess vnext.users must have exactly 1 entry, got %d\", m[\"tag\"], len(users))\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func vmessOneUser(ep map[string]any) bool {\n\tu, ok := ep[\"users\"].([]any)\n\treturn ok && len(u) == 1\n}","tryCatchPattern":null,"preventionTips":["Exactly one credential per outbound; never reuse inbound clients arrays as outbound users","Assert len(users)==1 in config tooling before emitting","Empty users arrays are invalid — always include the single {id, alterId, security} object"],"tags":["vmess","outbound","users","config","validation","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}