{"record":{"id":"cedf12c5aa0ea946","repo":"XTLS/Xray-core","slug":"shadowsocks-2022-accept-no-multi-servers","errorCode":null,"errorMessage":"Shadowsocks 2022 accept no multi servers","messagePattern":"Shadowsocks 2022 accept no multi servers","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/shadowsocks.go","lineNumber":242,"sourceCode":"\t\t\t\treturn nil, errors.New(\"Invalid Shadowsocks port.\")\n\t\t\t}\n\t\t\tif server.Password == \"\" {\n\t\t\t\treturn nil, errors.New(\"Shadowsocks password is not specified.\")\n\t\t\t}\n\n\t\t\tconfig := new(shadowsocks_2022.ClientConfig)\n\t\t\tconfig.Address = server.Address.Build()\n\t\t\tconfig.Port = uint32(server.Port)\n\t\t\tconfig.Method = server.Cipher\n\t\t\tconfig.Key = server.Password\n\t\t\treturn config, nil\n\t\t}\n\t}\n\n\tconfig := new(shadowsocks.ClientConfig)\n\tfor _, server := range v.Servers {\n\t\tif C.Contains(shadowaead_2022.List, server.Cipher) {\n\t\t\treturn nil, errors.New(\"Shadowsocks 2022 accept no multi servers\")\n\t\t}\n\t\tif server.Address == nil {\n\t\t\treturn nil, errors.New(\"Shadowsocks server address is not set.\")\n\t\t}\n\t\tif server.Port == 0 {\n\t\t\treturn nil, errors.New(\"Invalid Shadowsocks port.\")\n\t\t}\n\t\tif server.Password == \"\" {\n\t\t\treturn nil, errors.New(\"Shadowsocks password is not specified.\")\n\t\t}\n\t\taccount := &shadowsocks.Account{\n\t\t\tPassword: server.Password,\n\t\t}\n\t\taccount.CipherType = cipherFromString(server.Cipher)\n\t\tif account.CipherType == shadowsocks.CipherType_UNKNOWN {\n\t\t\treturn nil, errors.New(\"unknown cipher method: \", server.Cipher)\n\t\t}\n","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/shadowsocks.go#L224-L260","documentation":"In the legacy (non-2022) Shadowsocks outbound path, the builder iterates over all server entries; Shadowsocks-2022 ciphers are only allowed in the single-server fast path. Encountering a 2022 method while iterating multiple servers triggers this error — 2022 does not support the legacy multi-server array.","triggerScenarios":"Reaching the legacy loop with a 2022 cipher in any servers entry — practically, a 2022 server entry combined with entries that are not caught by the earlier single-2022 branch, e.g. the first server is classic and a later one uses a 2022 method.","commonSituations":"Mixing 2022 and classic servers in one outbound; adding a 2022 endpoint to an old multi-server list left over from V2Ray configs.","solutions":["Split 2022 servers into their own dedicated outbound with exactly one server.","Keep only classic AEAD ciphers in any multi-server legacy outbound.","Prefer separate outbounds + routing balancer for multiple endpoints of any type."],"exampleFix":"// before\n\"servers\": [\n  {\"address\": \"a.com\", \"port\": 443, \"method\": \"aes-128-gcm\", \"password\": \"...\"},\n  {\"address\": \"b.com\", \"port\": 443, \"method\": \"2022-blake3-aes-256-gcm\", \"password\": \"...\"}\n]\n\n// after: separate outbounds per endpoint, each with one server","handlingStrategy":"validation","validationCode":"var ss2022Prefixes = []string{\"2022-blake3-\"}\n\nfunc is2022Cipher(m string) bool {\n    for _, p := range ss2022Prefixes {\n        if strings.HasPrefix(m, p) {\n            return true\n        }\n    }\n    return false\n}\n\nfunc validServers(servers []Server) bool {\n    if len(servers) > 1 {\n        for _, s := range servers {\n            if is2022Cipher(s.Cipher) {\n                return false\n            }\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mix 2022 and classic entries in one outbound"],"tags":["shadowsocks-2022","outbound","multi-server","config"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}