{"record":{"id":"29575080b42ca241","repo":"hashicorp/nomad","slug":"set-contains-operators-require-an-rtarget","errorCode":null,"errorMessage":"Set contains operators require an RTarget","messagePattern":"Set contains operators require an RTarget","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10204,"sourceCode":"\t\tWeight:  a.Weight,\n\t}\n}\n\nfunc (a *Affinity) String() string {\n\treturn fmt.Sprintf(\"%s %s %s %v\", a.LTarget, a.Operand, a.RTarget, a.Weight)\n}\n\nfunc (a *Affinity) Validate() error {\n\tvar mErr multierror.Error\n\tif a.Operand == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing affinity operand\"))\n\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:","sourceCodeStart":10186,"sourceCodeEnd":10222,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10186-L10222","documentation":"An affinity (or set-contains constraint) uses operand set_contains_all / set_contains_any / set_contains, but its RTarget — the value that must (or any/all of whose elements must) be contained in the attribute's set — is empty. Affinity validation rejects it.","triggerScenarios":"Submitting an affinity like affinity { attribute = \"${meta.tags}\" operand = \"set_contains_all\" } with no value/RTarget set.","commonSituations":"Templated affinity generation where the interpolated value variable was empty; copy-paste of an affinity template with the value line deleted; confusion between the weight/attribute fields and the required value.","solutions":["Supply the required value field, e.g. value = \"gpu,fast\".","Verify templating renders a non-empty value.","If the intent was not set matching, pick a comparison operator that fits (but note set-contains requires a target)."],"exampleFix":"// before\naffinity {\n  attribute = \"${meta.node_tags}\"\n  operand   = \"set_contains_all\"\n  weight    = 50\n}\n// after\naffinity {\n  attribute = \"${meta.node_tags}\"\n  operand   = \"set_contains_all\"\n  value     = \"gpu,highmem\"\n  weight    = 50\n}","handlingStrategy":"validation","validationCode":"func affinityTargetAllowed(operand, rtarget string) bool {\n  switch operand {\n  case \"set_contains_all\", \"set_contains_any\", \"set_contains\":\n    return rtarget != \"\"\n  default:\n    return true\n  }\n}","typeGuard":null,"tryCatchPattern":"if slices.Contains([]string{\"set_contains\", \"set_contains_any\", \"set_contains_all\"}, operand) && rtarget == \"\" {\n  return fmt.Errorf(\"%s requires a value\", operand)\n}","preventionTips":["Always set value for set-contains affinities/constraints.","Assert non-empty interpolated values before rendering the job.","Add CI validation with nomad job validate."],"tags":["nomad","affinity","missing-value","job-validation"],"backgroundTag":"missing-required-argument","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"}