hashicorp/nomad · error
capacity_max (%d) cannot be less than existing provisioned c
Error message
capacity_max (%d) cannot be less than existing provisioned capacity (%d)
What it means
ValidateUpdate rejects shrinking a host volume's capacity_max below the capacity already provisioned on the node. If RequestedCapacityMaxBytes is positive and lower than existing.CapacityBytes, storage would be over-committed, so the update fails.
Source
Thrown at nomad/structs/host_volumes.go:198
if len(existing.Allocations) > 0 {
allocIDs := helper.ConvertSlice(existing.Allocations,
func(a *AllocListStub) string { return a.ID })
mErr = multierror.Append(mErr, fmt.Errorf(
"cannot update a volume in use: claimed by allocs (%s)",
strings.Join(allocIDs, ", ")))
}
if hv.NodeID != "" && hv.NodeID != existing.NodeID {
mErr = multierror.Append(mErr, errors.New("node ID cannot be updated"))
}
if hv.NodePool != "" && hv.NodePool != existing.NodePool {
mErr = multierror.Append(mErr, errors.New("node pool cannot be updated"))
}
if hv.RequestedCapacityMaxBytes > 0 &&
hv.RequestedCapacityMaxBytes < existing.CapacityBytes {
mErr = multierror.Append(mErr, fmt.Errorf(
"capacity_max (%d) cannot be less than existing provisioned capacity (%d)",
hv.RequestedCapacityMaxBytes, existing.CapacityBytes))
}
return mErr.ErrorOrNil()
}
const DefaultHostVolumePlugin = "default"
// CanonicalizeForCreate is called in the RPC handler to ensure we call client
// RPCs with correctly populated fields from the existing volume, even if the
// RPC request includes otherwise valid zero-values. This method should be
// called on request objects or a copy, never on a state store object directly.
func (hv *HostVolume) CanonicalizeForCreate(existing *HostVolume, now time.Time) {
if existing == nil {
hv.ID = uuid.Generate()
if hv.PluginID == "" {
hv.PluginID = DefaultHostVolumePlugin
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Raise RequestedCapacityMaxBytes to at least existing.CapacityBytes
- Set RequestedCapacityMaxBytes to 0 (unset) to leave the cap unchanged
- Rescale the actual storage on the node/CSI provider first, then update the volume
Example fix
// before RequestedCapacityMaxBytes: 5 * 1024 * 1024 * 1024 // 5GiB < provisioned // after RequestedCapacityMaxBytes: 20 * 1024 * 1024 * 1024 // >= existing capacity
Defensive patterns
Strategy: validation
Validate before calling
if hv.RequestedCapacityMaxBytes > 0 && hv.RequestedCapacityMaxBytes < existing.CapacityBytes {
return fmt.Errorf("capacity_max %d below provisioned %d", hv.RequestedCapacityMaxBytes, existing.CapacityBytes)
} Try / catch
if err := updateVolume(hv); err != nil {
if strings.Contains(err.Error(), "cannot be less than existing provisioned capacity") {
hv.RequestedCapacityMaxBytes = existing.CapacityBytes
}
} Prevention
- Fetch current capacity via volume status before setting capacity_max
- Use explicit unit math (GiB constants) to avoid byte-count typos
- Only set capacity_max when intentionally resizing
When it happens
Trigger: Updating a host volume with RequestedCapacityMaxBytes > 0 that is smaller than the node's current CapacityBytes for that volume (via the volume update path / validateVolumeUpdate).
Common situations: Operator tries to cap usage below what the CSI/Node reports as already provisioned; typo in byte count (e.g. GiB vs MiB); node resized independently of Nomad.
Related errors
- cannot register volume: node ID is required
- cannot register volume: host path is required
- missing name
- validate called on nil host volume capability
- capacity_max (%d) must be larger than capacity_min (%d)
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/a79930b6af5b43d1.
Report an issue: GitHub.