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

  1. Remove the distinct_hosts or distinct_property constraint from the host volume definition
  2. If the intent was scheduling spread, move the constraint to the job/task group instead of the volume
  3. 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

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


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