{"record":{"id":"f1b8f96d2ffdafe8","repo":"hashicorp/nomad","slug":"semver-constraint-is-invalid-v","errorCode":null,"errorMessage":"Semver constraint is invalid: %v","messagePattern":"Semver constraint is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10082,"sourceCode":"\t// Perform additional validation based on operand\n\tswitch c.Operand {\n\tcase ConstraintDistinctHosts:\n\t\trequireLtarget = false\n\tcase ConstraintSetContainsAll, ConstraintSetContainsAny, ConstraintSetContains:\n\t\tif c.RTarget == \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Set contains constraint requires an RTarget\"))\n\t\t}\n\tcase ConstraintRegex:\n\t\tif _, err := regexp.Compile(c.RTarget); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Regular expression failed to compile: %v\", err))\n\t\t}\n\tcase ConstraintVersion:\n\t\tif _, err := version.NewConstraint(c.RTarget); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Version constraint is invalid: %v\", err))\n\t\t}\n\tcase ConstraintSemver:\n\t\tif _, err := semver.NewConstraint(c.RTarget); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Semver constraint is invalid: %v\", err))\n\t\t}\n\tcase ConstraintDistinctProperty:\n\t\t// If a count is set, make sure it is convertible to a uint64\n\t\tif c.RTarget != \"\" {\n\t\t\tcount, err := strconv.ParseUint(c.RTarget, 10, 64)\n\t\t\tif err != nil {\n\t\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Failed to convert RTarget %q to uint64: %v\", c.RTarget, err))\n\t\t\t} else if count < 1 {\n\t\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Distinct Property must have an allowed count of 1 or greater: %d < 1\", count))\n\t\t\t}\n\t\t}\n\tcase ConstraintAttributeIsSet, ConstraintAttributeIsNotSet:\n\t\tif c.RTarget != \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Operator %q does not support an RTarget\", c.Operand))\n\t\t}\n\tcase \"=\", \"==\", \"is\", \"!=\", \"not\", \"<\", \"<=\", \">\", \">=\":\n\t\tif c.RTarget == \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Operator %q requires an RTarget\", c.Operand))","sourceCodeStart":10064,"sourceCodeEnd":10100,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10064-L10100","documentation":"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.","triggerScenarios":"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\".","commonSituations":"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.","solutions":["Rewrite the RTarget as valid SemVer 2 constraint syntax, e.g. \">= 1.2.0\" or \"~1.2.3\".","Pre-validate with semver.NewConstraint(target) in Go before submission.","Replace unsupported range operators with comma-separated comparator lists, e.g. \">= 1.2.0, < 1.3.0\" instead of \"^1.2.0\"."],"exampleFix":"// before\nconstraint {\n  attribute = \"${meta.app_version}\"\n  semver    = \"^1.4.0\"\n}\n// after\nconstraint {\n  attribute = \"${meta.app_version}\"\n  semver    = \">= 1.4.0, < 2.0.0\"\n}","handlingStrategy":"validation","validationCode":"import \"github.com/Masterminds/semver/v3\"\n\nfunc validSemverConstraint(target string) bool {\n  _, err := semver.NewConstraint(target)\n  return err == nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := semver.NewConstraint(c.RTarget); err != nil {\n  return fmt.Errorf(\"invalid semver constraint %q: %w\", c.RTarget, err)\n}","preventionTips":["Check Masterminds/semver docs for supported operators (~, ^ are supported there but not in go-version).","Test patterns against Masterminds/semver directly rather than assuming npm syntax.","Run nomad job validate in the deployment pipeline."],"tags":["nomad","constraint","semver","job-validation"],"backgroundTag":"invalid-version-constraint","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}