{"record":{"id":"50ac390e110a846e","repo":"XTLS/Xray-core","slug":"shadowsocks-2022-multi-user-users-must-have-emp","errorCode":null,"errorMessage":"shadowsocks 2022 (multi-user): users must have empty method","messagePattern":"shadowsocks 2022 \\(multi-user\\): users must have empty method","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/shadowsocks.go","lineNumber":140,"sourceCode":"\n\tif v.Cipher == \"\" {\n\t\treturn nil, errors.New(\"shadowsocks 2022 (multi-user): missing server method\")\n\t}\n\tif !strings.Contains(v.Cipher, \"aes\") {\n\t\treturn nil, errors.New(\"shadowsocks 2022 (multi-user): only blake3-aes-*-gcm methods are supported\")\n\t}\n\n\tif v.Users[0].Address == nil {\n\t\tconfig := new(shadowsocks_2022.MultiUserServerConfig)\n\t\tconfig.Method = v.Cipher\n\t\tconfig.Key = v.Password\n\t\tconfig.Network = v.NetworkList.Build()\n\n\t\tconfig.Users = make([]*protocol.User, len(v.Users))\n\t\tprocessUser := func(idx int) error {\n\t\t\tuser := v.Users[idx]\n\t\t\tif user.Cipher != \"\" {\n\t\t\t\treturn errors.New(\"shadowsocks 2022 (multi-user): users must have empty method\")\n\t\t\t}\n\t\t\taccount := &shadowsocks_2022.Account{\n\t\t\t\tKey: user.Password,\n\t\t\t}\n\t\t\tconfig.Users[idx] = &protocol.User{\n\t\t\t\tEmail:   user.Email,\n\t\t\t\tLevel:   uint32(user.Level),\n\t\t\t\tAccount: serial.ToTypedMessage(account),\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\tif err := task.ParallelForN(len(v.Users), processUser); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn config, nil\n\t}\n\n\tconfig := new(shadowsocks_2022.RelayServerConfig)","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/shadowsocks.go#L122-L158","documentation":"Shadowsocks-2022 multi-user mode derives each user's PSK with the server-wide method; per-user cipher fields are invalid. This error fires when any user entry in the users array has a non-empty 'cipher'/'method' value.","triggerScenarios":"A multi-user 2022 inbound where a user object includes \"cipher\": \"2022-blake3-aes-128-gcm\" or any non-empty method string.","commonSituations":"Reusing classic multi-user config structure where each user had its own cipher; generating users with a template that always fills the method field.","solutions":["Remove (or empty) the 'cipher'/'method' field from every entry in 'users'; keep only password, email, level.","Ensure the single server-level method matches all user key lengths (derive user keys from the same method's key size)."],"exampleFix":"// before\n\"users\": [{\"cipher\": \"2022-blake3-aes-128-gcm\", \"password\": \"...\"}]\n\n// after\n\"users\": [{\"password\": \"...\", \"email\": \"u1\"}]  // method only at server level","handlingStrategy":"validation","validationCode":"func validSS2022Users(users []User) bool {\n    for _, u := range users {\n        if u.Cipher != \"\" {\n            return false\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["User templates for 2022 must leave the method field unset"],"tags":["shadowsocks-2022","multi-user","config"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}