{"record":{"id":"e17f9cac1ba5bea9","repo":"XTLS/Xray-core","slug":"failed-to-get-cipher","errorCode":null,"errorMessage":"failed to get cipher","messagePattern":"failed to get cipher","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/shadowsocks/config.go","lineNumber":97,"sourceCode":"\t\t\tIVBytes:         32,\n\t\t\tAEADAuthCreator: createChaCha20Poly1305,\n\t\t}, nil\n\tcase CipherType_XCHACHA20_POLY1305:\n\t\treturn &AEADCipher{\n\t\t\tKeyBytes:        32,\n\t\t\tIVBytes:         32,\n\t\t\tAEADAuthCreator: createXChaCha20Poly1305,\n\t\t}, nil\n\tdefault:\n\t\treturn nil, errors.New(\"Unsupported cipher.\")\n\t}\n}\n\n// AsAccount implements protocol.AsAccount.\nfunc (a *Account) AsAccount() (protocol.Account, error) {\n\tCipher, err := a.getCipher()\n\tif err != nil {\n\t\treturn nil, errors.New(\"failed to get cipher\").Base(err)\n\t}\n\treturn &MemoryAccount{\n\t\tCipher:     Cipher,\n\t\tCipherType: a.CipherType,\n\t\tKey:        passwordToCipherKey([]byte(a.Password), Cipher.KeySize()),\n\t\tPassword:   a.Password,\n\t}, nil\n}\n\n// Cipher is an interface for all Shadowsocks ciphers.\ntype Cipher interface {\n\tKeySize() int32\n\tIVSize() int32\n\tNewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error)\n\tNewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error)\n\tIsAEAD() bool\n\tEncodePacket(key []byte, b *buf.Buffer) error\n\tDecodePacket(key []byte, b *buf.Buffer) error","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/shadowsocks/config.go#L79-L115","documentation":"Wrapper produced by Account.AsAccount() when getCipher() fails, i.e. always directly above [626]. It converts the raw 'Unsupported cipher.' error into an account-construction failure. Any component materializing a Shadowsocks account (server startup, dynamic user add, client outbound init) surfaces this instead of the bare cipher error.","triggerScenarios":"user.ToMemoryUser() / AsAccount() invoked on an account whose cipherType is unsupported — server NewServer, handler AddUser (API-driven user management), or client proxy creation.","commonSituations":"Adding users via the Xray API with a payload copied from an old config; panel/management tool (3x-ui style) sending a removed cipher; one bad user in a batch blocking whole inbound startup.","solutions":["Fix the cipher/method of the offending account as in [626] — this error has no independent cause.","When adding users via API, validate the method against the supported list before issuing the request.","In multi-user inbounds, locate the single bad entry (error usually surfaces per-user) and correct or remove it."],"exampleFix":"// before: API payload\n{ \"email\": \"u1\", \"method\": \"rc4-md5\", \"password\": \"x\" }\n// after\n{ \"email\": \"u1\", \"method\": \"aes-128-gcm\", \"password\": \"x\" }","handlingStrategy":"validation","validationCode":"// validate every account before calling ToMemoryUser/AsAccount\nfor _, u := range users {\n  if !isSupportedSSCipher(u.Method) {\n    return fmt.Errorf(\"user %s: unsupported cipher %q\", u.Email, u.Method)\n  }\n}","typeGuard":"func isSupportedSSCipher(m string) bool { /* see error 626 */ return false }","tryCatchPattern":"if _, err := account.AsAccount(); err != nil {\n  return fmt.Errorf(\"account %s unusable: %w\", account.Password[:0], err) // log base cause, fix cipher\n}","preventionTips":["Validate method fields at the API boundary before AddUser.","Reject legacy ciphers in panel/user-management code."],"tags":["shadowsocks","config","cipher","account","wrapper"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}