AlistGo/alist · critical

failed to create Cipher: %w

Error message

failed to create Cipher: %w

What it means

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.

Source

Thrown at drivers/crypt/driver.go:84

	if err != nil {
		return fmt.Errorf("can't find remote storage: %w", err)
	}
	d.remoteStorage = storage

	p, _ := strings.CutPrefix(d.Password, obfuscatedPrefix)
	p2, _ := strings.CutPrefix(d.Salt, obfuscatedPrefix)
	config := configmap.Simple{
		"password":                  p,
		"password2":                 p2,
		"filename_encryption":       d.FileNameEnc,
		"directory_name_encryption": d.DirNameEnc,
		"filename_encoding":         d.FileNameEncoding,
		"suffix":                    d.EncryptedSuffix,
		"pass_bad_blocks":           "",
	}
	c, err := rcCrypt.NewCipher(config)
	if err != nil {
		return fmt.Errorf("failed to create Cipher: %w", err)
	}
	d.cipher = c

	return nil
}

func (d *Crypt) updateObfusParm(str *string) error {
	temp := *str
	if !strings.HasPrefix(temp, obfuscatedPrefix) {
		temp, err := obscure.Obscure(temp)
		if err != nil {
			return err
		}
		temp = obfuscatedPrefix + temp
		*str = temp
	}
	return nil
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Re-enter the password and salt cleanly in the admin UI so they are re-obscured correctly, then save the storage
  2. Ensure FileNameEnc/DirNameEnc use valid values ('standard', 'obfuscate', or 'off') and filename_encoding is 'base32', 'base32768', or 'base64'
  3. 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
  4. If migrating from rclone, confirm the same password/salt pair works with rclone crypt on the same remote

Example fix

// before: salt field corrupted (double-obfuscated)
"salt": "::crypt::::crypt::XXXX"
// after: re-enter plain salt once in admin UI; stored as single obscured value
"salt": "::crypt::XXXX"
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check addition fields before Init
if addition.Password == "" { return errors.New("password required") }
if addition.FileNameEnc != "standard" && addition.FileNameEnc != "obfuscate" && addition.FileNameEnc != "off" {
    return fmt.Errorf("invalid filename_encryption: %s", addition.FileNameEnc)
}

Try / catch

if err := storage.Init(ctx); err != nil {
    if strings.Contains(err.Error(), "failed to create Cipher") {
        // credential/config corruption: re-enter password+salt rather than retrying
        return fmt.Errorf("crypt cipher config invalid, re-enter credentials: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/a625d771f0cee636. Report an issue: GitHub.