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
- Set the affinity operand explicitly (affinity { attribute = ...; value = ... } in HCL implies '=', or Operand = "=" in Go).
- Choose the intended operator (=, !=, regexp, version, set_contains, etc.) and populate it.
- Remove the empty affinity stanza if it was accidental.
- 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
- Default Operand to "=" when constructing affinities programmatically with LTarget/RTarget.
- Mirror your constraint construction helpers so both paths enforce the operand.
- Validate job specs in CI.
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
- Affinity %d validation failed: %s
- Semver affinity is invalid: %v
- Unknown affinity operator %q
- No LTarget provided but is required
- Affinity weight cannot be zero
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/86be006b18c3f8d3.
Report an issue: GitHub.