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 CreateVolumeResponseView on GitHub (pinned to 482b49bf1a)
Solutions
- Keep the requested topologies identical to the originally registered volume when updating
- If the topology must change, deregister the volume and register a new one in the target topology
- 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
- Freeze topology_request stanzas once a volume is created; manage topology changes as new volumes
- Avoid templating environment-specific values into topology segments used by existing volumes
- Diff RequestedTopologies with existing.Topologies before every update submission
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
- volume clone ID cannot be updated
- volume snapshot ID cannot be updated
- volume parameters cannot be updated
- volume name cannot be updated
- volume external ID cannot be updated
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/da6afa80e371225c.
Report an issue: GitHub.