hashicorp/nomad · error
volume external ID cannot be updated
Error message
volume external ID cannot be updated
What it means
Also produced by CSIVolume.Merge in nomad/structs/csi.go: an update may not change the volume's ExternalID (the provider-side identifier, e.g. an AWS EBS vol-* ID), because the volume object in Nomad permanently maps to that remote storage object. If the incoming volume has a different non-empty ExternalID than the registered one, Merge appends this error to the multierror.
Source
Thrown at nomad/structs/csi.go:793
// 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"))
}
// must be compatible with volume_capabilities
if v.AccessMode != CSIVolumeAccessModeUnknown ||
v.AttachmentMode != CSIVolumeAttachmentModeUnknown {View on GitHub (pinned to 482b49bf1a)
Solutions
- Register the new external ID as a different volume ID rather than mutating the existing registration.
- If the old remote volume is gone, deregister the CSI volume in Nomad and register it anew with the new external ID.
- Verify the intended external ID with `nomad volume status <id>` and correct your spec to match the existing registration.
Example fix
// before: reusing id ebs-0 with a new provider volume id = "ebs-0" external_id = "vol-999" // was vol-123 // after id = "ebs-1" external_id = "vol-999" // (or deregister ebs-0 and register fresh)
Defensive patterns
Strategy: validation
Validate before calling
existing, _ := client.Volumes().Get(ctx, volID)
if existing != nil && spec.ExternalID != "" && spec.ExternalID != existing.ExternalID {
return fmt.Errorf("volume %s: external_id is immutable; register a new volume ID", volID)
} Try / catch
if err := csiVolume.Merge(update); err != nil {
if strings.Contains(err.Error(), "volume external ID cannot be updated") {
return fmt.Errorf("provider volume changed: deregister and re-register with the new external_id")
}
return err
} Prevention
- When IaC recreates the backing storage volume, always register a new Nomad volume ID too.
- Compare external_id against `nomad volume status` output before re-applying specs.
- Avoid hand-editing external_id in existing volume definitions.
When it happens
Trigger: Re-registering/updating a CSI volume ID whose external_id differs from the one originally registered (e.g. pointing an existing volume ID at a newly provisioned cloud disk), or client-side volume reconciliation applying a spec with a changed ExternalID.
Common situations: Terraform/IaC recreating the underlying storage volume (new vol-xxx ID) while Nomad still references the old registration; manually editing the external_id in a volume HCL and re-applying it under the same ID.
Related errors
- volume name cannot be updated
- volume plugin ID cannot be updated
- CSI.ControllerAttachVolume: VolumeID is required
- CSI.ControllerAttachVolume: ClientCSINodeID is required
- CSI.ControllerDetachVolume: VolumeID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/9453bd84a4929c27.
Report an issue: GitHub.