XTLS/Xray-core · error
SOCKS servers: "users" should have one member at most. Multi
Error message
SOCKS servers: "users" should have one member at most. Multiple members in "users" should use multiple SOCKS outbounds and routing balancer instead
What it means
Xray-core rejects a SOCKS outbound (SocksClientConfig.Build, infra/conf/socks.go:105) whose server entry lists more than one member in the "users" array. Modern Xray allows at most one credential per SOCKS server entry; multi-credential setups must be modeled as multiple SOCKS outbounds combined with a routing balancer.
Source
Thrown at infra/conf/socks.go:105
func (v *SocksClientConfig) Build() (proto.Message, error) {
config := new(socks.ClientConfig)
if v.Address != nil {
v.Servers = []*SocksRemoteConfig{
{
Address: v.Address,
Port: v.Port,
},
}
if len(v.Username) > 0 {
v.Servers[0].Users = []json.RawMessage{{}}
}
}
if len(v.Servers) != 1 {
return nil, errors.New(`SOCKS settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple SOCKS outbounds and routing balancer instead`)
}
for _, serverConfig := range v.Servers {
if len(serverConfig.Users) > 1 {
return nil, errors.New(`SOCKS servers: "users" should have one member at most. Multiple members in "users" should use multiple SOCKS outbounds and routing balancer instead`)
}
server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port),
}
for _, rawUser := range serverConfig.Users {
user := new(protocol.User)
if v.Address != nil {
user.Level = v.Level
user.Email = v.Email
} else {
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse Socks user").Base(err).AtError()
}
}
account := new(SocksAccount)
if v.Address != nil {
account.Username = v.UsernameView on GitHub (pinned to 7d214f8b09)
Solutions
- Keep exactly one user object per servers[] entry: {"servers":[{"address":"1.2.3.4","port":1080,"users":[{"user":"u","pass":"p"}]}]}
- If you need multiple credentials/endpoints, define one socks outbound per credential and load-balance them with a routing "balancers" entry over their tags
- Prefer the simpler flat form: settings:{"address":"1.2.3.4","port":1080,"user":"u","pass":"p"}, which supports one user implicitly
Example fix
// before
"settings": { "servers": [ { "address": "1.2.3.4", "port": 1080,
"users": [ {"user":"a","pass":"x"}, {"user":"b","pass":"y"} ] } ] }
// after
"settings": { "servers": [ { "address": "1.2.3.4", "port": 1080,
"users": [ {"user":"a","pass":"x"} ] } ] }
// (second credential -> second socks outbound + routing balancer) Defensive patterns
Strategy: validation
Validate before calling
// JS: before writing config
const s = outbound.settings;
const servers = s.servers ?? [{address:s.address, port:s.port, users:s.user?[{user:s.user,pass:s.pass}]:[]}];
if (servers.length !== 1 || (servers[0].users?.length ?? 0) > 1) throw new Error('socks outbound: one server + at most one user; use multiple outbounds + balancer'); Try / catch
if (err.message.includes('users" should have one member')) { /* split into multiple outbounds and re-add balancer */ } Prevention
- Generate one socks outbound per credential
- Model failover with routing balancers over outbound tags, not user arrays
- Lint configs with a generator that encodes the one-user rule
When it happens
Trigger: An outbound with protocol "socks" whose "settings".servers[0].users contains 2 or more objects, e.g. {"servers":[{"address":"h","port":1,"users":[{...},{...}]}]}. Only fires in the new "servers" form; the legacy address/port/user/pass form cannot trigger it.
Common situations: Configs migrated from older Xray/V2Ray forks that permitted per-server user lists; copying a shared outbound template and appending users; scripts that generate one outbound per account but merge users into a single server.
Related errors
- failed to get outbound handler with tag: ${tag}
- existing tag found: ${tag}
- unsupported domain strategy: {}
- invalid redirect address: {}
- invalid redirect port: {}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/7bdd0c54969f6356.
Report an issue: GitHub.