hashicorp/nomad · error
Constraint %d validation failed: using unsupported operand %
Error message
Constraint %d validation failed: using unsupported operand %q
What it means
When validating a TaskGroup (or task resources struct), Nomad wraps constraint validation failures and explicitly rejects constraints using operands reserved for system-level handling: ConstraintDistinctHosts and ConstraintDistinctProperty. These operands are not permitted as ordinary constraints inside a job's constraint list.
Source
Thrown at nomad/structs/structs.go:3139
}
}
}
func (r *RequestedDevice) Validate() error {
if r == nil {
return nil
}
var mErr multierror.Error
if r.Name == "" {
_ = multierror.Append(&mErr, errors.New("device name must be given as one of the following: type, vendor/type, or vendor/type/name"))
}
for idx, constr := range r.Constraints {
// Ensure that the constraint doesn't use an operand we do not allow
switch constr.Operand {
case ConstraintDistinctHosts, ConstraintDistinctProperty:
outer := fmt.Errorf("Constraint %d validation failed: using unsupported operand %q", idx+1, constr.Operand)
_ = multierror.Append(&mErr, outer)
default:
if err := constr.Validate(); err != nil {
outer := fmt.Errorf("Constraint %d validation failed: %s", idx+1, err)
_ = multierror.Append(&mErr, outer)
}
}
}
for idx, affinity := range r.Affinities {
if err := affinity.Validate(); err != nil {
outer := fmt.Errorf("Affinity %d validation failed: %s", idx+1, err)
_ = multierror.Append(&mErr, outer)
}
}
return mErr.ErrorOrNil()
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove the distinct_hosts/distinct_property constraint and use the dedicated distinct_hosts = true field or the spread stanza instead
- If per-property spreading is needed, use the spread block rather than a constraint
- Re-validate with nomad job validate after restructuring
Example fix
// before
constraint {
attribute = "${node.unique.id}"
operand = "distinct_hosts"
}
// after
distinct_hosts = true Defensive patterns
Strategy: validation
Validate before calling
for _, c := range tg.Constraints {
if c.Operand == structs.ConstraintDistinctHosts || c.Operand == structs.ConstraintDistinctProperty {
return fmt.Errorf("use distinct_hosts field or spread stanza instead of operand %q", c.Operand)
}
} Type guard
func isAllowedConstraintOperand(op string) bool {
switch op {
case structs.ConstraintDistinctHosts, structs.ConstraintDistinctProperty:
return false
}
return true
} Prevention
- Use distinct_hosts = true and spread stanzas, never constraints with those operands
- Run nomad job validate before submission
- Keep job specs updated when upgrading Nomad (operands moved to dedicated fields)
When it happens
Trigger: Adding a constraint { attribute = "...", operand = "distinct_hosts" } (or distinct_property) directly in a job/task-group constraints block and submitting via nomad job run or the jobs API.
Common situations: Copy-pasting spread/anti-affinity configuration from old job examples before distinct_hosts moved to its own field; writing JSON job specs by hand and using the operand in the wrong place.
Related errors
- Constraint %d validation failed: %s
- <combined HCL diagnostics from str.String()>
- command cannot be empty
- Missing constraint operand
- no attribute provided but is required by operator
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/63197edee2d0bf1c.
Report an issue: GitHub.