{"record":{"id":"a625d771f0cee636","repo":"AlistGo/alist","slug":"failed-to-create-cipher-w","errorCode":null,"errorMessage":"failed to create Cipher: %w","messagePattern":"failed to create Cipher: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"drivers/crypt/driver.go","lineNumber":84,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"can't find remote storage: %w\", err)\n\t}\n\td.remoteStorage = storage\n\n\tp, _ := strings.CutPrefix(d.Password, obfuscatedPrefix)\n\tp2, _ := strings.CutPrefix(d.Salt, obfuscatedPrefix)\n\tconfig := configmap.Simple{\n\t\t\"password\":                  p,\n\t\t\"password2\":                 p2,\n\t\t\"filename_encryption\":       d.FileNameEnc,\n\t\t\"directory_name_encryption\": d.DirNameEnc,\n\t\t\"filename_encoding\":         d.FileNameEncoding,\n\t\t\"suffix\":                    d.EncryptedSuffix,\n\t\t\"pass_bad_blocks\":           \"\",\n\t}\n\tc, err := rcCrypt.NewCipher(config)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create Cipher: %w\", err)\n\t}\n\td.cipher = c\n\n\treturn nil\n}\n\nfunc (d *Crypt) updateObfusParm(str *string) error {\n\ttemp := *str\n\tif !strings.HasPrefix(temp, obfuscatedPrefix) {\n\t\ttemp, err := obscure.Obscure(temp)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttemp = obfuscatedPrefix + temp\n\t\t*str = temp\n\t}\n\treturn nil\n}","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/crypt/driver.go#L66-L102","documentation":"Thrown when rcCrypt.NewCipher rejects the crypt configuration assembled from the driver's Addition fields (password, salt, filename_encryption, directory_name_encryption, filename_encoding, suffix). NewCipher validates and derives the NaCl secretbox cipher; it fails when the password/salt values are not valid (e.g. not proper obscured strings after prefix stripping) or an encryption mode value is invalid. Without a cipher the driver cannot encrypt or decrypt anything, so Init aborts.","triggerScenarios":"Init with a password or salt that got mangled (e.g. manually edited in the DB, double-obscured, or containing the obfuscatedPrefix '::crypt::' incorrectly), or with an invalid filename_encryption / directory_name_encryption value (not one of the accepted 'standard'/'obfuscate'/'off' options), or a corrupted salt that fails key derivation (scrypt) parameters.","commonSituations":"Editing the storage record directly in the database instead of the admin UI; upgrading AList versions where the Addition schema changed; pasting a salt that includes the obfuscation prefix twice; supplying an empty password after the prefix strip when salt-based derivation expects non-empty input.","solutions":["Re-enter the password and salt cleanly in the admin UI so they are re-obscured correctly, then save the storage","Ensure FileNameEnc/DirNameEnc use valid values ('standard', 'obfuscate', or 'off') and filename_encoding is 'base32', 'base32768', or 'base64'","Check the wrapped error from NewCipher in logs — a base64/obscure decode failure points at password/salt corruption; re-create the storage if the credentials are unrecoverable","If migrating from rclone, confirm the same password/salt pair works with rclone crypt on the same remote"],"exampleFix":"// before: salt field corrupted (double-obfuscated)\n\"salt\": \"::crypt::::crypt::XXXX\"\n// after: re-enter plain salt once in admin UI; stored as single obscured value\n\"salt\": \"::crypt::XXXX\"","handlingStrategy":"try-catch","validationCode":"// Sanity-check addition fields before Init\nif addition.Password == \"\" { return errors.New(\"password required\") }\nif addition.FileNameEnc != \"standard\" && addition.FileNameEnc != \"obfuscate\" && addition.FileNameEnc != \"off\" {\n    return fmt.Errorf(\"invalid filename_encryption: %s\", addition.FileNameEnc)\n}","typeGuard":null,"tryCatchPattern":"if err := storage.Init(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to create Cipher\") {\n        // credential/config corruption: re-enter password+salt rather than retrying\n        return fmt.Errorf(\"crypt cipher config invalid, re-enter credentials: %w\", err)\n    }\n    return err\n}","preventionTips":["Always set password/salt through the admin UI so obscuring is applied exactly once","Never hand-edit obscured credential columns in the database","When upgrading AList major versions, re-save crypt storages to rebuild ciphers with current defaults","Keep a tested backup of the password/salt pair; losing them makes remote data undecryptable"],"tags":["crypt","cipher","config","credentials"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}