{"record":{"id":"745fdaf63feb6474","repo":"XTLS/Xray-core","slug":"create-service-745fda","errorCode":null,"errorMessage":"create service","messagePattern":"create service","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/shadowsocks_2022/inbound_multi.go","lineNumber":80,"sourceCode":"\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)\n\t}\n\terr = service.UpdateUsersWithPasswords(\n\t\tC.MapIndexed(memUsers, func(index int, it *protocol.MemoryUser) int { return index }),\n\t\tC.Map(memUsers, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }),\n\t)\n\tif err != nil {\n\t\treturn nil, errors.New(\"create service\").Base(err)\n\t}\n\n\tinbound.service = service\n\treturn inbound, nil\n}\n\n// AddUser implements proxy.UserManager.AddUser().\nfunc (i *MultiUserInbound) AddUser(ctx context.Context, u *protocol.MemoryUser) error {\n\ti.Lock()\n\tdefer i.Unlock()\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/shadowsocks_2022/inbound_multi.go#L62-L98","documentation":"Wrapper when shadowaead_2022.NewMultiService fails while building the multi-user 2022 inbound. Same class of cause as [634] but for the multi-user service constructor with the decoded server PSK: key length incompatible with config.Method, or the method string invalid at the service layer.","triggerScenarios":"NewMultiService[method, psk, ...] rejecting the method/psk pair — e.g. 2022-blake3-aes-128-gcm paired with a 32-byte PSK, or a method name that passed the earlier list check but is rejected by the library's own switch.","commonSituations":"Changing the method after generating the key without resizing it; keys shared from a different-method server; copy-paste between 128-bit and 256-bit deployments.","solutions":["Match PSK byte length to method: 16 bytes for *-aes-128-*, 32 bytes for *-aes-256-* and *chacha20*.","Regenerate keys for both server PSK and per-user keys after any method change.","Read the base error — it names the length/method constraint that failed."],"exampleFix":"// before: 32-byte PSK with a 128-bit method\n\"method\": \"2022-blake3-aes-128-gcm\", \"key\": \"<base64-of-32-bytes>\"\n// after\n\"method\": \"2022-blake3-aes-128-gcm\", \"key\": \"<base64-of-16-bytes>\"","handlingStrategy":"validation","validationCode":"raw, _ := base64.StdEncoding.DecodeString(config.Key)\nwant := 32\nif strings.Contains(config.Method, \"128\") { want = 16 }\nif len(raw) != want {\n  return fmt.Errorf(\"server PSK must be %d bytes for %s\", want, config.Method)\n}","typeGuard":"func keyMatchesMethod(method string, n int) bool {\n  if strings.Contains(method, \"128\") { return n == 16 }\n  return n == 32\n}","tryCatchPattern":"service, err := shadowaead_2022.NewMultiService[int](config.Method, psk, 500, inbound, nil)\nif err != nil {\n  return fmt.Errorf(\"multi service init failed (method/PSK size mismatch?): %w\", err)\n}","preventionTips":["Regenerate all keys whenever the method changes.","Keep a single source of truth mapping method -> key size in provisioning code."],"tags":["shadowsocks-2022","key-length","config","multi-user","startup"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}