juicedata/juicefs · error

cannot update volume %s from %v to %v

Error message

cannot update volume %s from %v to %v

What it means

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.

Source

Thrown at pkg/meta/config.go:145

		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 != "" {
		f.SessionToken = "removed"
	}
	if f.EncryptKey != "" {
		f.EncryptKey = "removed"
	}
}

func (f *Format) String() string {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Read the error's field/value list and revert the immutable field to its current value
  2. For legitimate storage migration, use the supported procedure (e.g. juicefs sync for data, keep same bucket config) instead of mutating the format
  3. For capacity/quota or updatable options, set only those fields in --update

Example fix

// before
juicefs format --update --storage s3 --bucket new-bucket meta-url
// after
juicefs format --update --capacity 1024 meta-url  # only updatable options
Defensive patterns

Strategy: validation

Validate before calling

old, err := loadStoredFormat(metaURL)
if err != nil { return err }
for _, immutable := range []string{"Storage", "Bucket", "MetaVersion", "BlockSize"} {
    if reflect.ValueOf(newF).FieldByName(immutable) != reflect.ValueOf(old).FieldByName(immutable) {
        return fmt.Errorf("%s cannot be changed via update", immutable)
    }
}

Try / catch

if err := cmd.FormatUpdate(...); err != nil && strings.Contains(err.Error(), "cannot update volume") {
    // parse field/values from error and revert those flags
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/479069489d3e8ec9. Report an issue: GitHub.