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).

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)

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.