{"record":{"id":"52c0231ad9727a01","repo":"XTLS/Xray-core","slug":"http-servers-users-should-have-one-member-at-mo","errorCode":null,"errorMessage":"HTTP servers: \"users\" should have one member at most. Multiple members in \"users\" should use multiple HTTP outbounds and routing balancer instead","messagePattern":"HTTP servers: \"users\" should have one member at most\\. Multiple members in \"users\" should use multiple HTTP outbounds and routing balancer instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/http.go","lineNumber":87,"sourceCode":"func (v *HTTPClientConfig) Build() (proto.Message, error) {\n\tconfig := new(http.ClientConfig)\n\tif v.Address != nil {\n\t\tv.Servers = []*HTTPRemoteConfig{\n\t\t\t{\n\t\t\t\tAddress: v.Address,\n\t\t\t\tPort:    v.Port,\n\t\t\t},\n\t\t}\n\t\tif len(v.Username) > 0 {\n\t\t\tv.Servers[0].Users = []json.RawMessage{{}}\n\t\t}\n\t}\n\tif len(v.Servers) != 1 {\n\t\treturn nil, errors.New(`HTTP settings: \"servers\" should have one and only one member. Multiple endpoints in \"servers\" should use multiple HTTP outbounds and routing balancer instead`)\n\t}\n\tfor _, serverConfig := range v.Servers {\n\t\tif len(serverConfig.Users) > 1 {\n\t\t\treturn nil, errors.New(`HTTP servers: \"users\" should have one member at most. Multiple members in \"users\" should use multiple HTTP outbounds and routing balancer instead`)\n\t\t}\n\t\tserver := &protocol.ServerEndpoint{\n\t\t\tAddress: serverConfig.Address.Build(),\n\t\t\tPort:    uint32(serverConfig.Port),\n\t\t}\n\t\tfor _, rawUser := range serverConfig.Users {\n\t\t\tuser := new(protocol.User)\n\t\t\tif v.Address != nil {\n\t\t\t\tuser.Level = v.Level\n\t\t\t\tuser.Email = v.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(\"failed to parse HTTP user\").Base(err).AtError()\n\t\t\t\t}\n\t\t\t}\n\t\t\taccount := new(HTTPAccount)\n\t\t\tif v.Address != nil {\n\t\t\t\taccount.Username = v.Username","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/http.go#L69-L105","documentation":"Thrown by the HTTP outbound builder when a server entry's users array has more than one member. Each HTTP outbound authenticates with at most one credential pair; multiple credentials require multiple HTTP outbounds and a routing balancer. An empty users array is allowed (no auth).","triggerScenarios":"Putting two or more user objects inside httpSettings.servers[0].users; mixing the legacy username/password fields with an extra users entry is safe (legacy path synthesizes exactly one user), but explicit users arrays with 2+ entries fail.","commonSituations":"Users trying to encode failover credentials for several upstream proxies in one outbound; generated configs that emit a users list unconditionally.","solutions":["Keep users to zero or one entry per server","Move each credential to its own HTTP outbound and use a routing balancer to distribute traffic"],"exampleFix":"// before\n\"users\": [ {\"user\":\"a\",\"pass\":\"x\"}, {\"user\":\"b\",\"pass\":\"y\"} ]\n// after\n\"users\": [ {\"user\":\"a\",\"pass\":\"x\"} ]  // second credential in a separate HTTP outbound","handlingStrategy":"validation","validationCode":"for _, s := range httpSettings.Servers {\n\tif len(s.Users) > 1 {\n\t\treturn fmt.Errorf(\"server %v has %d users; max is 1\", s.Address, len(s.Users))\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Encode at most one credential per HTTP outbound","Lint generated configs for users arrays longer than 1"],"tags":["xray","config","http","auth","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}