hashicorp/nomad · error

volume name cannot be updated

Error message

volume name cannot be updated

What it means

This error comes from CSIVolume.Merge (nomad/structs/csi.go), which is used (e.g. by reconcileVolume) to apply updated volume claims onto an existing CSIVolume. Immutable identity fields of a volume — its Name, ExternalID, PluginID, CloneID — may not change once registered. When a proposed update carries a different, non-empty Name than the existing volume, Merge appends "volume name cannot be updated" to the returned multierror.

Source

Thrown at nomad/structs/csi.go:790

	}
	return nil
}

// Merge updates the mutable fields of a volume with those from
// another volume. CSIVolume has many user-defined fields which are
// immutable once set, and many fields that are not
// user-settable. Merge will return an error if we try to mutate the
// user-defined immutable fields after they're set, but silently
// ignore fields that are controlled by Nomad.
func (v *CSIVolume) Merge(other *CSIVolume) error {
	if other == nil {
		return nil
	}

	var errs *multierror.Error

	if v.Name != other.Name && other.Name != "" {
		errs = multierror.Append(errs, errors.New("volume name cannot be updated"))
	}
	if v.ExternalID != other.ExternalID && other.ExternalID != "" {
		errs = multierror.Append(errs, errors.New(
			"volume external ID cannot be updated"))
	}
	if v.PluginID != other.PluginID {
		errs = multierror.Append(errs, errors.New(
			"volume plugin ID cannot be updated"))
	}
	if v.CloneID != other.CloneID && other.CloneID != "" {
		errs = multierror.Append(errs, errors.New(
			"volume clone ID cannot be updated"))
	}
	if v.SnapshotID != other.SnapshotID && other.SnapshotID != "" {
		errs = multierror.Append(errs, errors.New(
			"volume snapshot ID cannot be updated"))
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Keep the volume name identical to the existing registration, or deregister the volume (nomad volume deregister) and register it fresh under the new name.
  2. Use a distinct volume ID for the renamed volume instead of reusing the old ID.
  3. Diff the existing volume (nomad volume status <id>) against your spec to spot mismatched immutable fields before submitting.

Example fix

// before
volume "old-name" {
  type   = "csi"
  id     = "ebs-0"  // previously registered as name "ebs-0" too
  external_id = "vol-123"
}

// after: either keep the name
csi_volume "ebs-0" { ... }

// or deregister then re-register with the new name
// nomad volume deregister ebs-0
// nomad volume register new.hcl
Defensive patterns

Strategy: validation

Validate before calling

existing, _ := client.Volumes().Get(ctx, volID)
if existing != nil && volSpec.Name != existing.Name {
    return fmt.Errorf("volume %s: name is immutable; deregister before renaming", volID)
}

Try / catch

if err := csiVolume.Merge(update); err != nil {
    if strings.Contains(err.Error(), "volume name cannot be updated") {
        return fmt.Errorf("keep the volume name or deregister and re-register")
    }
    return err
}

Prevention

When it happens

Trigger: Submitting a volume registration/update for a CSI volume ID whose spec has a different `name` than the previously registered volume (e.g. `nomad volume update`/register path, or a client reconcile of a volume claim where the stored volume's Name differs from the incoming one).

Common situations: Re-registering a volume after renaming it in the jobspec; copying a volume block from another job with a different name but the same volume ID; state drift after restoring volumes from a snapshot/backup.

Related errors


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