hashicorp/nomad · error

Unknown constraint type %q

Error message

Unknown constraint type %q

What it means

The constraint's Operand string does not match any operator Nomad recognizes (version, regex, is_set, comparison operators, set-contains, etc.), so it falls to the default case and is rejected as an unknown constraint type. Job submission fails validation.

Source

Thrown at nomad/structs/structs.go:10103

		// If a count is set, make sure it is convertible to a uint64
		if c.RTarget != "" {
			count, err := strconv.ParseUint(c.RTarget, 10, 64)
			if err != nil {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("Failed to convert RTarget %q to uint64: %v", c.RTarget, err))
			} else if count < 1 {
				mErr.Errors = append(mErr.Errors, fmt.Errorf("Distinct Property must have an allowed count of 1 or greater: %d < 1", count))
			}
		}
	case ConstraintAttributeIsSet, ConstraintAttributeIsNotSet:
		if c.RTarget != "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Operator %q does not support an RTarget", c.Operand))
		}
	case "=", "==", "is", "!=", "not", "<", "<=", ">", ">=":
		if c.RTarget == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Operator %q requires an RTarget", c.Operand))
		}
	default:
		mErr.Errors = append(mErr.Errors, fmt.Errorf("Unknown constraint type %q", c.Operand))
	}

	// If the constraint must have a "LTarget" (attribute in the job spec), then
	// ensure it is not an empty string and is valid.
	if requireLtarget {
		if c.LTarget == "" {
			mErr.Errors = append(mErr.Errors, errors.New("no attribute provided but is required by operator"))
		} else {
			if err := validateConstraintAttribute(c.LTarget); err != nil {
				mErr.Errors = append(mErr.Errors, err)
			}
		}

	}

	return mErr.ErrorOrNil()
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Correct the operand to a supported one: =, ==, is, !=, not, <, <=, >, >=, version, regex, semver, set_contains, set_contains_any, set_contains_all, is_set, is_not_set, distinct_property.
  2. Use the job spec's sugar syntax (version = ">= 1.2", regexp = "...") instead of raw operands where possible.
  3. Run nomad job validate to catch the typo before submission.

Example fix

// before
constraint {
  attribute = "${attr.kernel.version}"
  operand   = "verison"
  value     = ">= 4.4"
}
// after
constraint {
  attribute = "${attr.kernel.version}"
  version   = ">= 4.4"
}
Defensive patterns

Strategy: validation

Validate before calling

var validOperands = map[string]bool{
  "=": true, "==": true, "is": true, "!=": true, "not": true,
  "<": true, "<=": true, ">": true, ">=": true,
  "version": true, "regex": true, "semver": true,
  "set_contains": true, "set_contains_any": true, "set_contains_all": true,
  "is_set": true, "is_not_set": true, "distinct_property": true,
}

func validOperand(op string) bool { return validOperands[op] }

Try / catch

if !validOperands[operand] {
  return fmt.Errorf("unknown constraint operand %q", operand)
}

Prevention

When it happens

Trigger: Submitting a job with a typo'd operand such as "verison", "Version", "between", or an operand removed/renamed in a newer Nomad version.

Common situations: Hand-written HCL with misspelled operand; migrating jobs between Nomad versions where an operand changed; using sugar fields (version/regexp/semver/distinct_property) incorrectly as operands; case-sensitivity mistakes.

Related errors


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