{"record":{"id":"558ce537b63bd40a","repo":"juicedata/juicefs","slug":"decrypt-format-s","errorCode":null,"errorMessage":"decrypt format: %s","messagePattern":"decrypt format: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/config.go","lineNumber":137,"sourceCode":"\t\tvar args []interface{}\n\t\tswitch {\n\t\tcase f.Name != old.Name:\n\t\t\targs = []interface{}{\"name\", old.Name, f.Name}\n\t\tcase f.BlockSize != old.BlockSize:\n\t\t\targs = []interface{}{\"block size\", old.BlockSize, f.BlockSize}\n\t\tcase f.Compression != old.Compression:\n\t\t\targs = []interface{}{\"compression\", old.Compression, f.Compression}\n\t\tcase f.Shards != old.Shards:\n\t\t\targs = []interface{}{\"shards\", old.Shards, f.Shards}\n\t\tcase f.HashPrefix != old.HashPrefix:\n\t\t\targs = []interface{}{\"hash prefix\", old.HashPrefix, f.HashPrefix}\n\t\tcase f.MetaVersion != old.MetaVersion:\n\t\t\targs = []interface{}{\"meta version\", old.MetaVersion, f.MetaVersion}\n\t\t}\n\t\tif args == nil {\n\t\t\tif f.UUID != old.UUID {\n\t\t\t\tif err := f.Decrypt(); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"decrypt format: %s\", err)\n\t\t\t\t}\n\t\t\t\tf.UUID = old.UUID // UUID cannot be changed alone\n\t\t\t\tif err := f.Encrypt(); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"encrypt format: %s\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"cannot update volume %s from %v to %v\", args...)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (f *Format) RemoveSecret() {\n\tif f.SecretKey != \"\" {\n\t\tf.SecretKey = \"removed\"\n\t}\n\tif f.SessionToken != \"\" {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/config.go#L119-L155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\njuicefs format --update --encrypt-key NEW_KEY meta-url\n// after\njuicefs format --update --encrypt-key OLD_KEY meta-url  # key that decrypts stored secrets\n# then rotate keys using the documented key-rotation flow","handlingStrategy":"validation","validationCode":"keyData, err := os.ReadFile(keyFile)\nif err != nil || len(keyData) == 0 {\n    return fmt.Errorf(\"encryption key file missing or empty\")\n}\n// verify key decrypts format before update:\nprobe := format; if err := probe.Decrypt(); err != nil { /* wrong key */ }","typeGuard":null,"tryCatchPattern":"err := format.Update(old)\nvar keyErr *os.PathError\nif err != nil && strings.HasPrefix(err.Error(), \"decrypt format\") {\n    // prompt for the correct original encryption key\n}","preventionTips":["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"],"tags":["encryption","format","config","decrypt"],"backgroundTag":"decryption-key-mismatch","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}