{"record":{"id":"450554778cf9a3ce","repo":"hashicorp/nomad","slug":"semver-affinity-is-invalid-v","errorCode":null,"errorMessage":"Semver affinity is invalid: %v","messagePattern":"Semver affinity is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10216,"sourceCode":"\t}\n\n\t// Perform additional validation based on operand\n\tswitch a.Operand {\n\tcase ConstraintSetContainsAll, ConstraintSetContainsAny, ConstraintSetContains:\n\t\tif a.RTarget == \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Set contains operators require an RTarget\"))\n\t\t}\n\tcase ConstraintRegex:\n\t\tif _, err := regexp.Compile(a.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(a.RTarget); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Version affinity is invalid: %v\", err))\n\t\t}\n\tcase ConstraintSemver:\n\t\tif _, err := semver.NewConstraint(a.RTarget); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Semver affinity is invalid: %v\", err))\n\t\t}\n\tcase \"=\", \"==\", \"is\", \"!=\", \"not\", \"<\", \"<=\", \">\", \">=\":\n\t\tif a.RTarget == \"\" {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Operator %q requires an RTarget\", a.Operand))\n\t\t}\n\tdefault:\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Unknown affinity operator %q\", a.Operand))\n\t}\n\n\t// Ensure we have an LTarget\n\tif a.LTarget == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"No LTarget provided but is required\"))\n\t}\n\n\t// Ensure that weight is between -100 and 100, and not zero\n\tif a.Weight == 0 {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Affinity weight cannot be zero\"))\n\t}","sourceCodeStart":10198,"sourceCodeEnd":10234,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10198-L10234","documentation":"This error comes from Affinity.Validate() in nomad/structs/structs.go. When an affinity uses the 'semver' operator (ConstraintSemver), Nomad parses the affinity's RTarget with hashicorp/go-version's semver.NewConstraint. If the target string is not a valid semver constraint, validation fails with 'Semver affinity is invalid: <parse error>'. It exists to catch malformed version constraints at job-submission time rather than at scheduling time.","triggerScenarios":"Submitting a job (via nomad job run / /v1/jobs API) whose task/group affinity has operand \"semver\" and an RTarget that fails semver.NewConstraint, e.g. \"~> 2\" with invalid spacing, \"1.x\", \"latest\", or an empty RTarget.","commonSituations":"Copy-pasting npm-style version ranges (which go-version's semver parser does not accept), typos like \"v1.2..3\", forgetting to quote ranges in HCL, or switching an affinity from \"version\" to \"semver\" without adjusting the constraint syntax.","solutions":["Fix the RTarget to be a valid semver constraint accepted by hashicorp/go-version's semver.NewConstraint (e.g. \"~> 1.2.0\", \">= 1.2, < 2.0\").","If you need non-semver range syntax (like \"1.x\"), use the \"version\" operator instead of \"semver\".","Ensure RTarget is non-empty when operand is \"semver\"."],"exampleFix":"// before\naffinity {\n  attribute = \"attr.meta.app_version\"\n  operator  = \"semver\"\n  value     = \"1.x\"\n}\n// after\naffinity {\n  attribute = \"attr.meta.app_version\"\n  operator  = \"semver\"\n  value     = \"~> 1.0\"\n}","handlingStrategy":"validation","validationCode":"func validSemverConstraint(s string) bool { _, err := semver.NewConstraint(s); return err == nil }\n// before submit: check every affinity with operand \"semver\"","typeGuard":"func isSemverOperand(op string) bool { return op == \"semver\" }","tryCatchPattern":null,"preventionTips":["Lint job specs against hashicorp/go-version semver syntax before nomad job run","Prefer the \"version\" operator when you need non-semver range syntax","Never leave value empty on a semver affinity"],"tags":["nomad","affinity","semver","job-spec","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"}