hashicorp/nomad · error

Missing affinity operand

Error message

Missing affinity operand

What it means

Affinity.Validate() appends this error when the affinity's Operand field is empty. Like constraints, affinities require an operator (e.g. =, regexp, set_contains, distinct_hosts) to interpret the scoring expression; a missing operand makes the affinity invalid and the job submission is rejected via the multierror.

Source

Thrown at nomad/structs/structs.go:10197

	if a == nil {
		return nil
	}
	return &Affinity{
		LTarget: a.LTarget,
		RTarget: a.RTarget,
		Operand: a.Operand,
		Weight:  a.Weight,
	}
}

func (a *Affinity) String() string {
	return fmt.Sprintf("%s %s %s %v", a.LTarget, a.Operand, a.RTarget, a.Weight)
}

func (a *Affinity) Validate() error {
	var mErr multierror.Error
	if a.Operand == "" {
		mErr.Errors = append(mErr.Errors, errors.New("Missing affinity operand"))
	}

	// Perform additional validation based on operand
	switch a.Operand {
	case ConstraintSetContainsAll, ConstraintSetContainsAny, ConstraintSetContains:
		if a.RTarget == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Set contains operators require an RTarget"))
		}
	case ConstraintRegex:
		if _, err := regexp.Compile(a.RTarget); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Regular expression failed to compile: %v", err))
		}
	case ConstraintVersion:
		if _, err := version.NewConstraint(a.RTarget); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Version affinity is invalid: %v", err))
		}
	case ConstraintSemver:
		if _, err := semver.NewConstraint(a.RTarget); err != nil {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set the affinity operand explicitly (affinity { attribute = ...; value = ... } in HCL implies '=', or Operand = "=" in Go).
  2. Choose the intended operator (=, !=, regexp, version, set_contains, etc.) and populate it.
  3. Remove the empty affinity stanza if it was accidental.
  4. Validate locally with `nomad job validate`.

Example fix

// before (Go)
a := &structs.Affinity{LTarget: "${node.datacenter}", RTarget: "dc1", Weight: 50}
// after
a := &structs.Affinity{LTarget: "${node.datacenter}", Operand: "=", RTarget: "dc1", Weight: 50}
Defensive patterns

Strategy: validation

Validate before calling

func validateAffinityOperand(a *structs.Affinity) error {
	if a.Operand == "" {
		return fmt.Errorf("affinity %q: operand is required", a.LTarget)
	}
	return nil
}

Type guard

func hasAffinityOperand(a *structs.Affinity) bool { return a != nil && a.Operand != "" }

Prevention

When it happens

Trigger: Submitting an affinity stanza with only attribute/value (and weight) but no operator, or constructing Affinity{LTarget, RTarget, Weight} in Go without Operand before calling Validate.

Common situations: Hand-written JSON job specs that omit the operator key; job-generation tooling mirroring constraint code that also skipped Operand; users porting an HCL constraint like `attr = "value"` (implicit '=' operand in HCL) into raw API calls.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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