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

  1. Remove the distinct_hosts/distinct_property constraint and use the dedicated distinct_hosts = true field or the spread stanza instead
  2. If per-property spreading is needed, use the spread block rather than a constraint
  3. 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

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


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