hashicorp/nomad · error

volume topology request update was not compatible with exist

Error message

volume topology request update was not compatible with existing topology

What it means

Raised by CSIVolume.Merge (nomad/structs/csi.go:834) when an update changes the requested topologies of a CSI volume that already has resolved topologies. CSI topologies are immutable: once the storage provider reports where the volume lives (zones, racks, regions), the request must remain compatible with it.

Source

Thrown at nomad/structs/csi.go:834

				ok = true
				break
			}
		}
		if ok {
			v.RequestedCapabilities = other.RequestedCapabilities
		} else {
			errs = multierror.Append(errs, errors.New(
				"volume requested capabilities update was not compatible with existing capability in use"))
		}
	} else {
		v.RequestedCapabilities = other.RequestedCapabilities
	}

	// topologies are immutable, so topology request changes must be
	// compatible with the existing topology, if any
	if len(v.Topologies) > 0 {
		if !v.RequestedTopologies.Equal(other.RequestedTopologies) {
			errs = multierror.Append(errs, errors.New(
				"volume topology request update was not compatible with existing topology"))
		}
	}

	// 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

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Keep the requested topologies identical to the originally registered volume when updating
  2. If the topology must change, deregister the volume and register a new one in the target topology
  3. Verify the spec diff before update — only mutable fields (secrets, context, mount options when not in use, compatible capabilities) should differ

Example fix

// before
topology_request {
  segments { topology = "rack", value = "rack-2" } # changed from rack-1
}
// after
topology_request {
  segments { topology = "rack", value = "rack-1" } # unchanged, matches existing volume
}
Defensive patterns

Strategy: validation

Validate before calling

if len(existing.Topologies) > 0 && !existing.RequestedTopologies.Equal(update.RequestedTopologies) {
    return errors.New("requested topologies are immutable; deregister and create a new volume")
}

Type guard

func topologiesMutable(existing, update *structs.CSIVolume) bool {
    return len(existing.Topologies) == 0 || existing.RequestedTopologies.Equal(update.RequestedTopologies)
}

Prevention

When it happens

Trigger: Submitting a volume update where `len(v.Topologies) > 0` and `!v.RequestedTopologies.Equal(other.RequestedTopologies)` — i.e. the requested topologies in the update differ from the volume's stored requested topologies.

Common situations: Moving a volume spec to a different availability zone/region and re-submitting; adding or removing a topology segment in HCL; infrastructure changes (new zones) leading to regenerated specs with different topology constraints.

Related errors


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