hashicorp/nomad · error

volume parameters cannot be updated

Error message

volume parameters cannot be updated

What it means

Raised by CSIVolume.Merge (nomad/structs/csi.go:855) when a volume update changes the `parameters` map. Volume parameters are passed to the storage provider's CreateVolume call and are baked into the external volume; changing them after creation would contradict what the provider already provisioned, so they are immutable (empty submitted parameters are ignored).

Solutions

  1. Remove or keep parameters identical in the update spec — omitting them entirely (empty map) bypasses the check
  2. Deregister and re-register the volume (optionally creating a new external volume) if the parameters must change
  3. Diff the volume spec against the registered volume before submitting updates

Example fix

// before
parameters = {
  provisioning = "thick" # differs from registered 'thin'
}
// after
# parameters omitted from update; immutable after creation
volume "data" {
  type = "csi"
}
Defensive patterns

Strategy: validation

Validate before calling

if len(update.Parameters) != 0 && !maps.Equal(existing.Parameters, update.Parameters) {
    return errors.New("parameters are immutable; remove them from the update or create a new volume")
}

Type guard

func parametersMutable(existing, update *structs.CSIVolume) bool {
    return len(update.Parameters) == 0 || maps.Equal(existing.Parameters, update.Parameters)
}

Prevention

When it happens

Trigger: Submitting a volume update where `len(other.Parameters) != 0` and `!maps.Equal(v.Parameters, other.Parameters)` — i.e. non-empty parameters that differ from the registered ones.

Common situations: Editing provisioning parameters (e.g. storage class, iops, provisioner keys) in the HCL spec and re-running `nomad volume update`; environment-specific templating injecting different parameters; typo fixes to parameter keys resubmitted as updates.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/b5241977b478b8b4. Report an issue: GitHub.

Appendix: source

Thrown at nomad/structs/csi.go:855

	}

	// MountOptions can be updated so long as the volume isn't in use
	if v.InUse() {
		if !v.MountOptions.Equal(other.MountOptions) {
			errs = multierror.Append(errs, errors.New(
				"can not update mount options while volume is in use"))
		}
	} else {
		v.MountOptions = other.MountOptions
	}

	// Secrets can be updated freely
	v.Secrets = other.Secrets

	// must be compatible with parameters set by from CreateVolumeResponse

	if len(other.Parameters) != 0 && !maps.Equal(v.Parameters, other.Parameters) {
		errs = multierror.Append(errs, errors.New(
			"volume parameters cannot be updated"))
	}

	// Context is mutable and will be used during controller validation, but we
	// need to ensure we don't remove context that's been previously stored
	// server-side if the user has submitted an update without adding it to the
	// spec manually (which we should not require)
	if len(other.Context) != 0 {
		v.Context = other.Context
	}
	return errs.ErrorOrNil()
}

// Request and response wrappers
type CSIVolumeRegisterRequest struct {
	Volumes   []*CSIVolume
	Timestamp int64 // UnixNano

View on GitHub (pinned to 482b49bf1a)