{"record":{"id":"479069489d3e8ec9","repo":"juicedata/juicefs","slug":"cannot-update-volume-s-from-v-to-v","errorCode":null,"errorMessage":"cannot update volume %s from %v to %v","messagePattern":"cannot update volume (.+?) from (.+?) to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/config.go","lineNumber":145,"sourceCode":"\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\"\n\t}\n}\n\nfunc (f *Format) String() string {","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/config.go#L127-L163","documentation":"Refused volume update: the requested format change touches an immutable field (e.g. storage type, bucket, meta version) that cannot be modified via update, with args describing field old→new values. The library prevents silent changes that would make existing data unreachable.","triggerScenarios":"juicefs format --update attempting to change a non-updatable setting (storage backend, bucket, block size, MetaVersion, etc.); update() builds args only for these guarded fields and errors when args != nil.","commonSituations":"Trying to migrate object storage by editing the format; accidental typo causing a storage/bucket mismatch; attempting a metadata version downgrade; scripted format updates including fields that are deliberately immutable.","solutions":["Read the error's field/value list and revert the immutable field to its current value","For legitimate storage migration, use the supported procedure (e.g. juicefs sync for data, keep same bucket config) instead of mutating the format","For capacity/quota or updatable options, set only those fields in --update"],"exampleFix":"// before\njuicefs format --update --storage s3 --bucket new-bucket meta-url\n// after\njuicefs format --update --capacity 1024 meta-url  # only updatable options","handlingStrategy":"validation","validationCode":"old, err := loadStoredFormat(metaURL)\nif err != nil { return err }\nfor _, immutable := range []string{\"Storage\", \"Bucket\", \"MetaVersion\", \"BlockSize\"} {\n    if reflect.ValueOf(newF).FieldByName(immutable) != reflect.ValueOf(old).FieldByName(immutable) {\n        return fmt.Errorf(\"%s cannot be changed via update\", immutable)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := cmd.FormatUpdate(...); err != nil && strings.Contains(err.Error(), \"cannot update volume\") {\n    // parse field/values from error and revert those flags\n}","preventionTips":["Only pass explicitly updatable options to --update","Diff the new format against `juicefs status` output before applying","Use supported migration tooling (juicefs sync) for storage changes instead of editing format fields"],"tags":["format","config","update","immutable-field"],"backgroundTag":"conflicting-config-options","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"}