hashicorp/nomad · error

Semver constraint is invalid: %v

Error message

Semver constraint is invalid: %v

What it means

Nomad affinity/constraint validation failed because a "semver" operand's RTarget is not a parseable semantic-version constraint. Nomad uses Masterminds/semver's NewConstraint, which supports SemVer 2.0 expressions like ">= 1.2.3-rc.1". The parse error is wrapped into the job's validation multi-error and blocks submission.

Source

Thrown at nomad/structs/structs.go:10082

	// Perform additional validation based on operand
	switch c.Operand {
	case ConstraintDistinctHosts:
		requireLtarget = false
	case ConstraintSetContainsAll, ConstraintSetContainsAny, ConstraintSetContains:
		if c.RTarget == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Set contains constraint requires an RTarget"))
		}
	case ConstraintRegex:
		if _, err := regexp.Compile(c.RTarget); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Regular expression failed to compile: %v", err))
		}
	case ConstraintVersion:
		if _, err := version.NewConstraint(c.RTarget); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Version constraint is invalid: %v", err))
		}
	case ConstraintSemver:
		if _, err := semver.NewConstraint(c.RTarget); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Semver constraint is invalid: %v", err))
		}
	case ConstraintDistinctProperty:
		// 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))

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Rewrite the RTarget as valid SemVer 2 constraint syntax, e.g. ">= 1.2.0" or "~1.2.3".
  2. Pre-validate with semver.NewConstraint(target) in Go before submission.
  3. Replace unsupported range operators with comma-separated comparator lists, e.g. ">= 1.2.0, < 1.3.0" instead of "^1.2.0".

Example fix

// before
constraint {
  attribute = "${meta.app_version}"
  semver    = "^1.4.0"
}
// after
constraint {
  attribute = "${meta.app_version}"
  semver    = ">= 1.4.0, < 2.0.0"
}
Defensive patterns

Strategy: validation

Validate before calling

import "github.com/Masterminds/semver/v3"

func validSemverConstraint(target string) bool {
  _, err := semver.NewConstraint(target)
  return err == nil
}

Try / catch

if _, err := semver.NewConstraint(c.RTarget); err != nil {
  return fmt.Errorf("invalid semver constraint %q: %w", c.RTarget, err)
}

Prevention

When it happens

Trigger: Submitting a job with constraint or affinity operand "semver" and an RTarget that semver.NewConstraint rejects, e.g. "1.2" with strict parsing context, "v^1.2" (caret syntax not supported), or stray characters like "~= 2.0".

Common situations: Using npm/cargo-style range operators (~, ^, ~=) unsupported by Masterminds/semver; missing patch segment in contexts requiring full X.Y.Z; typos like double dots; migrating a constraint from "version" to "semver" operand without reformatting the target.

Related errors


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