juicedata/juicefs · error
decrypt format: %s
Error message
decrypt format: %s
What it means
Wraps a failure from Format.Decrypt() inside update() when reconciling a volume format with the stored one. When only the UUID differs but encryption is configured, the new format must be decrypted with the (new) key; failure means the supplied encryption key/secret cannot decrypt the format, so the update is rejected.
Source
Thrown at pkg/meta/config.go:137
var args []interface{}
switch {
case f.Name != old.Name:
args = []interface{}{"name", old.Name, f.Name}
case f.BlockSize != old.BlockSize:
args = []interface{}{"block size", old.BlockSize, f.BlockSize}
case f.Compression != old.Compression:
args = []interface{}{"compression", old.Compression, f.Compression}
case f.Shards != old.Shards:
args = []interface{}{"shards", old.Shards, f.Shards}
case f.HashPrefix != old.HashPrefix:
args = []interface{}{"hash prefix", old.HashPrefix, f.HashPrefix}
case f.MetaVersion != old.MetaVersion:
args = []interface{}{"meta version", old.MetaVersion, f.MetaVersion}
}
if args == nil {
if f.UUID != old.UUID {
if err := f.Decrypt(); err != nil {
return fmt.Errorf("decrypt format: %s", err)
}
f.UUID = old.UUID // UUID cannot be changed alone
if err := f.Encrypt(); err != nil {
return fmt.Errorf("encrypt format: %s", err)
}
}
} else {
return fmt.Errorf("cannot update volume %s from %v to %v", args...)
}
}
return nil
}
func (f *Format) RemoveSecret() {
if f.SecretKey != "" {
f.SecretKey = "removed"
}
if f.SessionToken != "" {View on GitHub (pinned to c9a67b23e8)
Solutions
- Supply the correct --encrypt-key (the key that can decrypt the format's secrets)
- Inspect the wrapped error (%s) to distinguish bad key vs malformed ciphertext
- If migrating keys, first decrypt with the old key, update, then re-encrypt with the new key via the proper rotation procedure
Example fix
// before juicefs format --update --encrypt-key NEW_KEY meta-url // after juicefs format --update --encrypt-key OLD_KEY meta-url # key that decrypts stored secrets # then rotate keys using the documented key-rotation flow
Defensive patterns
Strategy: validation
Validate before calling
keyData, err := os.ReadFile(keyFile)
if err != nil || len(keyData) == 0 {
return fmt.Errorf("encryption key file missing or empty")
}
// verify key decrypts format before update:
probe := format; if err := probe.Decrypt(); err != nil { /* wrong key */ } Try / catch
err := format.Update(old)
var keyErr *os.PathError
if err != nil && strings.HasPrefix(err.Error(), "decrypt format") {
// prompt for the correct original encryption key
} Prevention
- Keep encryption key files backed up alongside volume configuration
- Test key rotation in a staging volume before production
- Always pass the OLD key when updating a format with existing encrypted secrets
When it happens
Trigger: juicefs format --update or doInit path where f.UUID != old.UUID and f.Decrypt() fails — typically wrong --encrypt-key (AES/SM4) that doesn't match the key used to encrypt the format, or malformed encrypted fields.
Common situations: Rotating encryption keys with the wrong new key supplied; missing or corrupted encrypt key file; copying a format between environments without its key; TestFormat_Update_KeyConflict exercises exactly this conflict path.
Related errors
- encrypt format: %s
- format decrypt: %s
- %w: please set the 'JFS_RSA_PASSPHRASE' environment variable
- create %sor: %w
- cannot update volume %s from %v to %v
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/558ce537b63bd40a.
Report an issue: GitHub.