hashicorp/nomad · error

Constraint %d validation failed: %s

Error message

Constraint %d validation failed: %s

What it means

A generic wrapper raised while validating a task group's Constraints: for each constraint that fails Constraint.Validate() for any reason other than the special distinct operands, Nomad wraps the underlying error as "Constraint %d validation failed: <reason>" (1-indexed). The inner text explains the actual problem (missing LTarget/RTarget, unknown operand, regexp error, etc.).

Source

Thrown at nomad/structs/structs.go:3143

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()
}

// NodeResources is used to define the resources available on a client node.
type NodeResources struct {
	// Do not read from this value except for compatibility (i.e. serialization).
	//

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the inner error after the colon to identify the exact constraint problem
  2. Fix the constraint's operand/attribute/value to satisfy Constraint.Validate()
  3. Run nomad job validate locally before submitting

Example fix

// before
constraint {
  attribute = "${meta.rack}"
  operand   = "="
  # RTarget missing
}
// after
constraint {
  attribute = "${meta.rack}"
  operand   = "="
  RTarget   = "r1"
}
Defensive patterns

Strategy: validation

Validate before calling

for i, c := range tg.Constraints {
    if err := c.Validate(); err != nil {
        return fmt.Errorf("constraint %d: %w", i+1, err)
    }
}

Type guard

func hasConstraintOperands(l, op, r string) bool { return l != "" && op != "" && r != "" }

Prevention

When it happens

Trigger: Submitting a job with a malformed constraint, e.g. operand = "=" with a missing RTarget, an invalid regexp operand value, or an empty attribute, via nomad job run or the jobs API.

Common situations: Hand-writing constraint stanzas with wrong operand names (e.g. "equals" instead of "="); referencing node attributes that don't exist isn't caught here, but structural problems are; templating constraints dynamically and producing empty fields.

Related errors


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