{"record":{"id":"2c78fd3d0964b76f","repo":"XTLS/Xray-core","slug":"socks-settings-servers-should-have-one-and-only","errorCode":null,"errorMessage":"SOCKS settings: \"servers\" should have one and only one member. Multiple endpoints in \"servers\" should use multiple SOCKS outbounds and routing balancer instead","messagePattern":"SOCKS settings: \"servers\" should have one and only one member\\. Multiple endpoints in \"servers\" should use multiple SOCKS outbounds and routing balancer instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/socks.go","lineNumber":101,"sourceCode":"\tPassword string               `json:\"pass\"`\n\tServers  []*SocksRemoteConfig `json:\"servers\"`\n}\n\nfunc (v *SocksClientConfig) Build() (proto.Message, error) {\n\tconfig := new(socks.ClientConfig)\n\tif v.Address != nil {\n\t\tv.Servers = []*SocksRemoteConfig{\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(`SOCKS settings: \"servers\" should have one and only one member. Multiple endpoints in \"servers\" should use multiple SOCKS 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(`SOCKS servers: \"users\" should have one member at most. Multiple members in \"users\" should use multiple SOCKS 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 Socks user\").Base(err).AtError()\n\t\t\t\t}","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/socks.go#L83-L119","documentation":"The SOCKS outbound historically allowed a 'servers' array but this implementation restricts it to exactly one member (with a shorthand top-level address form normalized first). Multiple endpoints must instead be modeled as separate SOCKS outbounds plus a routing balancer; zero servers likewise fails.","triggerScenarios":"A SOCKS outbound with settings.servers of length != 1 — an empty array, or two entries like [proxyA, proxyB] — and no top-level 'address' that would have been normalized to one entry.","commonSituations":"Legacy V2Ray 2.x/3.x configs with multiple SOCKS servers in one outbound; attempting failover by listing several upstream SOCKS proxies; omitting both the shorthand address and servers.","solutions":["Keep exactly one server in 'servers', or use the shorthand form with top-level 'address'/'port'/'users'.","For multiple upstream proxies, define one SOCKS outbound per endpoint and a routing balancer selecting them.","Remove an empty 'servers' array entirely and fill the shorthand fields."],"exampleFix":"// before\n\"outbounds\": [{\n  \"protocol\": \"socks\",\n  \"settings\": {\"servers\": [{\"address\": \"a.com\", \"port\": 1080}, {\"address\": \"b.com\", \"port\": 1080}]}\n}]\n\n// after\n\"outbounds\": [\n  {\"tag\": \"socks-a\", \"protocol\": \"socks\", \"settings\": {\"servers\": [{\"address\": \"a.com\", \"port\": 1080}]}},\n  {\"tag\": \"socks-b\", \"protocol\": \"socks\", \"settings\": {\"servers\": [{\"address\": \"b.com\", \"port\": 1080}]}}\n],\n\"routing\": {\"balancers\": [{\"tag\": \"socks-bal\", \"selector\": [\"socks-a\", \"socks-b\"]}]}","handlingStrategy":"validation","validationCode":"func validSocksOutbound(settings map[string]any) bool {\n    servers, ok := settings[\"servers\"].([]any)\n    if !ok {\n        _, hasAddr := settings[\"address\"]\n        return hasAddr\n    }\n    return len(servers) == 1\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use separate SOCKS outbounds plus a balancer for multiple upstreams","Migrate legacy multi-server arrays during V2Ray-to-Xray upgrades"],"tags":["socks","outbound","balancer","config"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}