{"record":{"id":"46f08ac012f2f570","repo":"hashicorp/nomad","slug":"set-contains-constraint-requires-an-rtarget","errorCode":null,"errorMessage":"Set contains constraint requires an RTarget","messagePattern":"Set contains constraint requires an RTarget","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10070,"sourceCode":"}\n\nfunc (c *Constraint) Validate() error {\n\tvar mErr multierror.Error\n\tif c.Operand == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing constraint operand\"))\n\t}\n\n\t// requireLtarget specifies whether the constraint requires an LTarget to be\n\t// provided.\n\trequireLtarget := true\n\n\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 {","sourceCodeStart":10052,"sourceCodeEnd":10088,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10052-L10088","documentation":"Constraints using set-contains operands (set_contains, set_contains_all, set_contains_any) require a non-empty RTarget listing the set membership values to check against. An empty RTarget makes the constraint meaningless, so validation fails.","triggerScenarios":"constraint { operand = \"set_contains\" } with no 'value'/'rtarget' field set, or value = \"\" — e.g. generated HCL where the attribute was dropped.","commonSituations":"Programmatic job generation omitting the value for set-contains constraints; hand-written constraints copying the distinct_hosts form (which needs no ltarget/rtarget pair semantics); refactors that rename fields and lose the value.","solutions":["Add a value listing items, e.g. constraint { operand = \"set_contains\", attribute = \"${meta.roles}\", value = \"web\" }.","Remove the constraint if it is not needed.","Check job-submission code paths so the RTarget is always populated for set-contains operands."],"exampleFix":"// before\nconstraint {\n  operand   = \"set_contains\"\n  attribute = \"${node.meta.roles}\"\n}\n// after\nconstraint {\n  operand   = \"set_contains\"\n  attribute = \"${node.meta.roles}\"\n  value     = \"web\"\n}","handlingStrategy":"validation","validationCode":"if operand == \"set_contains\" || operand == \"set_contains_all\" || operand == \"set_contains_any\" {\n    if value == \"\" { return errors.New(\"set-contains constraint requires a value\") }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set 'value' for set-contains constraints","Check generated HCL for dropped fields","Test job validation (nomad job validate) in CI"],"tags":["nomad","constraint","validation","job-spec"],"backgroundTag":"constraint-validation-failed","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"}