{"record":{"id":"bbd0c40fc5368959","repo":"XTLS/Xray-core","slug":"failed-to-get-shadowsocks-user-bbd0c4","errorCode":null,"errorMessage":"failed to get shadowsocks user","messagePattern":"failed to get shadowsocks user","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/shadowsocks_2022/inbound_multi.go","lineNumber":62,"sourceCode":"}\n\nfunc NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiUserInbound, error) {\n\tnetworks := config.Network\n\tif len(networks) == 0 {\n\t\tnetworks = []net.Network{\n\t\t\tnet.Network_TCP,\n\t\t\tnet.Network_UDP,\n\t\t}\n\t}\n\tmemUsers := []*protocol.MemoryUser{}\n\tfor i, user := range config.Users {\n\t\tif user.Email == \"\" {\n\t\t\tu := uuid.New()\n\t\t\tuser.Email = \"unnamed-user-\" + strconv.Itoa(i) + \"-\" + u.String()\n\t\t}\n\t\tu, err := user.ToMemoryUser()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"failed to get shadowsocks user\").Base(err).AtError()\n\t\t}\n\t\tmemUsers = append(memUsers, u)\n\t}\n\n\tinbound := &MultiUserInbound{\n\t\tnetworks: networks,\n\t\tusers:    memUsers,\n\t}\n\tif config.Key == \"\" {\n\t\treturn nil, errors.New(\"missing key\")\n\t}\n\tpsk, err := base64.StdEncoding.DecodeString(config.Key)\n\tif err != nil {\n\t\treturn nil, errors.New(\"parse config\").Base(err)\n\t}\n\tservice, err := shadowaead_2022.NewMultiService[int](config.Method, psk, 500, inbound, nil)\n\tif err != nil {\n\t\treturn nil, errors.New(\"create service\").Base(err)","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/shadowsocks_2022/inbound_multi.go#L44-L80","documentation":"Multi-user 2022 inbound equivalent of [628]: while converting config.Users to memory users, one ToMemoryUser() call failed and the whole inbound build aborts (AtError). Note this handler auto-assigns a synthetic email (unnamed-user-<i>-<uuid>) when email is blank, so the failure is about the account itself — bad method/cipher per user — not about missing emails.","triggerScenarios":"NewMultiUserInbound construction where a user entry in a shadowsocks-2022 multi-user config has an invalid method (non-2022 cipher reaching the account layer) or otherwise fails account materialization.","commonSituations":"Mixing classic-AEAD per-user entries into a shadowsocks-2022 multi config; panels writing aes-256-gcm into user entries; per-user keys of wrong length for the inbound method.","solutions":["Set each user's method to the inbound's 2022 method and each user's key to a correctly sized base64 PSK-derived value.","Remember the multi inbound structure: server-level key in `key`, per-user keys under users[].","Validate with xray run -test and fix the user flagged by the base error."],"exampleFix":"// before\n\"users\": [ { \"email\": \"u1\", \"method\": \"aes-128-gcm\", \"password\": \"...\" } ]\n// after (shadowsocks-2022 multi)\n\"users\": [ { \"email\": \"u1\", \"method\": \"2022-blake3-aes-128-gcm\", \"password\": \"<base64-16B-key>\" } ]","handlingStrategy":"validation","validationCode":"for i, u := range config.Users {\n  if !isSS2022Method(u.Method) {\n    return fmt.Errorf(\"user %d (%s): method %q is not a shadowsocks-2022 method\", i, u.Email, u.Method)\n  }\n}","typeGuard":"func isSS2022Method(m string) bool { /* see error 633 */ return false }","tryCatchPattern":"u, err := user.ToMemoryUser()\nif err != nil {\n  return fmt.Errorf(\"user %q invalid (check method/key): %w\", user.Email, err)\n}","preventionTips":["Give every user entry an explicit email even though the handler auto-generates one.","Validate each user's method and key length before inbound build."],"tags":["shadowsocks-2022","multi-user","config","users","startup"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}