hashicorp/nomad · error
invalid constraint %s: host volumes of the same name are alw
Error message
invalid constraint %s: host volumes of the same name are always on distinct hosts
What it means
Host volume validation rejects constraint operands that would be meaningless on a host volume: DistinctHosts and DistinctProperty. Because each host volume is bound to a specific node, volumes of the same name are inherently on distinct hosts, so these constraints are redundant and therefore rejected. Validation walks every constraint on the HostVolume and appends this error for each offending operand.
Source
Thrown at nomad/structs/host_volumes.go:165
"capacity_max (%d) must be larger than capacity_min (%d)",
hv.RequestedCapacityMaxBytes, hv.RequestedCapacityMinBytes))
}
for _, cap := range hv.RequestedCapabilities {
err := cap.Validate()
if err != nil {
mErr = multierror.Append(mErr, err)
}
}
for _, constraint := range hv.Constraints {
if err := constraint.Validate(); err != nil {
mErr = multierror.Append(mErr, fmt.Errorf("invalid constraint: %v", err))
}
switch constraint.Operand {
case ConstraintDistinctHosts, ConstraintDistinctProperty:
mErr = multierror.Append(mErr, fmt.Errorf(
"invalid constraint %s: host volumes of the same name are always on distinct hosts", constraint.Operand))
default:
}
}
return helper.FlattenMultierror(mErr.ErrorOrNil())
}
// ValidateUpdate verifies that an update to a volume is safe to make.
func (hv *HostVolume) ValidateUpdate(existing *HostVolume) error {
if existing == nil {
return nil
}
var mErr *multierror.Error
if len(existing.Allocations) > 0 {
allocIDs := helper.ConvertSlice(existing.Allocations,
func(a *AllocListStub) string { return a.ID })
mErr = multierror.Append(mErr, fmt.Errorf(View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the distinct_hosts or distinct_property constraint from the host volume definition
- If the intent was scheduling spread, move the constraint to the job/task group instead of the volume
- Re-run nomad job validate / volume validate before submitting
Example fix
// before
Constraints: []*Constraint{{Operand: "distinct_hosts"}}
// after
Constraints: nil // distinct-hosts semantics are implicit for host volumes Defensive patterns
Strategy: validation
Validate before calling
for _, c := range hv.Constraints {
if c.Operand == "distinct_hosts" || c.Operand == "distinct_property" {
return fmt.Errorf("constraint %s not allowed on host volumes", c.Operand)
}
} Type guard
func isForbiddenVolumeConstraint(op string) bool {
return op == structs.ConstraintDistinctHosts || op == structs.ConstraintDistinctProperty
} Prevention
- Never copy job/task constraint blocks into host volume definitions
- Run nomad volume validate in CI before submitting volume specs
- Lint HCL for distinct_hosts/distinct_property under host volume blocks
When it happens
Trigger: Calling HostVolume.Validate (directly or via the volume register/update RPC -> validateVolumeUpdate) with a Constraints entry whose Operand is set to 'distinct_hosts' or 'distinct_property'.
Common situations: Copy-pasting a task/group constraint block into a host volume definition; migrating job-level volume config into the new host volume spec; tooling generating constraints generically without filtering by object type.
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
- Missing constraint operand
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3a5c3d6e7346b876.
Report an issue: GitHub.