{"record":{"id":"d568c8430d5afa0a","repo":"hashicorp/nomad","slug":"missing-constraint-operand","errorCode":null,"errorMessage":"Missing constraint operand","messagePattern":"Missing constraint operand","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10057,"sourceCode":"func (c *Constraint) Copy() *Constraint {\n\tif c == nil {\n\t\treturn nil\n\t}\n\treturn &Constraint{\n\t\tLTarget: c.LTarget,\n\t\tRTarget: c.RTarget,\n\t\tOperand: c.Operand,\n\t}\n}\n\nfunc (c *Constraint) String() string {\n\treturn fmt.Sprintf(\"%s %s %s\", c.LTarget, c.Operand, c.RTarget)\n}\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}","sourceCodeStart":10039,"sourceCodeEnd":10075,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10039-L10075","documentation":"Constraint.Validate() appends this error when the constraint's Operand field is empty. The operand defines the comparison operator (=, !=, regexp, set_contains, etc.) and is required for Nomad to interpret the constraint; without it the constraint is meaningless and rejected.","triggerScenarios":"Submitting a job/group/task constraint stanza with no operator — in HCL, writing only `attribute = \"...\"` and `value = \"...\"` without `operator`; in Go, constructing Constraint{LTarget, RTarget} and leaving Operand \"\" before Validate.","commonSituations":"Users assuming '=' is implied like in some tools (in Nomad HCL, `attr = value` sets operand implicitly, but raw JSON/API construction misses it); programmatic job builders copying fields selectively; API consumers migrating from other schedulers' filter syntax.","solutions":["Set the constraint operator explicitly, e.g. constraint { attribute = \"${meta.rack}\"; value = \"r1\" } which sets operand \"=\"; or set Operand = \"=\" in Go.","If building via JSON API, ensure the constraint object's Operand key is populated (canonicalize/parse normally sets \"=\" for HCL).","Remove the empty constraint stanza entirely if it was unintentional.","Use `nomad job validate` to catch it before submission."],"exampleFix":"// before (Go)\nc := &structs.Constraint{LTarget: \"${meta.rack}\", RTarget: \"r1\"}\n// after\nc := &structs.Constraint{LTarget: \"${meta.rack}\", RTarget: \"r1\", Operand: \"=\"}","handlingStrategy":"validation","validationCode":"func validateConstraintOperand(c *structs.Constraint) error {\n\tif c.Operand == \"\" {\n\t\treturn fmt.Errorf(\"constraint %q: operand is required\", c.LTarget)\n\t}\n\treturn nil\n}","typeGuard":"func hasOperand(c *structs.Constraint) bool { return c != nil && c.Operand != \"\" }","tryCatchPattern":null,"preventionTips":["When building constraints programmatically, default Operand to \"=\" if unset.","Prefer HCL authoring where `attr = value` implies the operand.","Validate the job spec in CI with `nomad job validate`."],"tags":["nomad","constraint","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"}