{"record":{"id":"3107b137b1030e6b","repo":"juicedata/juicefs","slug":"encrypt-format-s","errorCode":null,"errorMessage":"encrypt format: %s","messagePattern":"encrypt format: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/config.go","lineNumber":141,"sourceCode":"\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 != \"\" {\n\t\tf.SessionToken = \"removed\"\n\t}\n\tif f.EncryptKey != \"\" {\n\t\tf.EncryptKey = \"removed\"","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/config.go#L123-L159","documentation":"Wraps a failure from Format.Encrypt() inside update() after the old UUID has been restored. It means the format's secrets could not be encrypted with the configured key/cipher, so the volume update is aborted to avoid persisting unencrypted or invalid secrets.","triggerScenarios":"juicefs format --update where UUID changed and f.Encrypt() fails — invalid key length for the chosen cipher (AES-128/256-GCM or SM4), unsupported cipher algorithm, or corrupted plaintext secret fields.","commonSituations":"Switching cipher algorithm with a key of the wrong size; malformed key string in the key file; environment where the SM4/AES implementation is unavailable or misconfigured.","solutions":["Verify the encryption key length matches the cipher (16/32 bytes for AES, 16-byte derived key for SM4)","Check the wrapped error (%s) for the exact crypto failure and fix the key file content","Retry the update with a valid key; do not force-write a format with failed encryption"],"exampleFix":"// before\nkey := \"short-key\" // invalid length for AES-256-GCM\n// after\nkey := loadKeyFile(\"/path/to/key\") // 32 random bytes, e.g. from `openssl rand -hex 32`","handlingStrategy":"validation","validationCode":"keyLen := len(keyBytes)\nswitch cipherAlgo {\ncase \"aes128\":\n    if keyLen != 16 { return errors.New(\"AES-128 key must be 16 bytes\") }\ncase \"aes256\", \"sm4\":\n    if keyLen != 32 { return errors.New(\"key must be 32 bytes\") }\n}","typeGuard":null,"tryCatchPattern":"if err := f.Encrypt(); err != nil {\n    // abort update; never persist partially encrypted format\n    return fmt.Errorf(\"encrypt format: %s\", err)\n}","preventionTips":["Generate keys with a CSPRNG at the exact required length","Match key length to the configured cipher algorithm","Round-trip test (Encrypt then Decrypt) after any key or cipher change"],"tags":["encryption","format","config","encrypt"],"backgroundTag":"invalid-config-value","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"}