{"record":{"id":"6edc4ecdff0250d5","repo":"hashicorp/nomad","slug":"affinity-d-validation-failed-s","errorCode":null,"errorMessage":"Affinity %d validation failed: %s","messagePattern":"Affinity (.+?) validation failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":3150,"sourceCode":"\t\t_ = multierror.Append(&mErr, errors.New(\"device name must be given as one of the following: type, vendor/type, or vendor/type/name\"))\n\t}\n\n\tfor idx, constr := range r.Constraints {\n\t\t// Ensure that the constraint doesn't use an operand we do not allow\n\t\tswitch constr.Operand {\n\t\tcase ConstraintDistinctHosts, ConstraintDistinctProperty:\n\t\t\touter := fmt.Errorf(\"Constraint %d validation failed: using unsupported operand %q\", idx+1, constr.Operand)\n\t\t\t_ = multierror.Append(&mErr, outer)\n\t\tdefault:\n\t\t\tif err := constr.Validate(); err != nil {\n\t\t\t\touter := fmt.Errorf(\"Constraint %d validation failed: %s\", idx+1, err)\n\t\t\t\t_ = multierror.Append(&mErr, outer)\n\t\t\t}\n\t\t}\n\t}\n\tfor idx, affinity := range r.Affinities {\n\t\tif err := affinity.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Affinity %d validation failed: %s\", idx+1, err)\n\t\t\t_ = multierror.Append(&mErr, outer)\n\t\t}\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n\n// NodeResources is used to define the resources available on a client node.\ntype NodeResources struct {\n\t// Do not read from this value except for compatibility (i.e. serialization).\n\t//\n\t// Deprecated; use NodeProcessorResources instead.\n\tCpu LegacyNodeCpuResources\n\n\tProcessors NodeProcessorResources\n\tMemory     NodeMemoryResources\n\tDisk       NodeDiskResources\n\tDevices    []*NodeDeviceResource","sourceCodeStart":3132,"sourceCodeEnd":3168,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L3132-L3168","documentation":"Raised during TaskGroup validation when an Affinity stanza fails Affinity.Validate(); the underlying reason is wrapped as \"Affinity %d validation failed: <reason>\" with a 1-based index. Affinities share the constraint-like structure (attribute, operand, value) and must pass the same kind of structural checks.","triggerScenarios":"Submitting a job whose task group affinity has an invalid operand or missing attribute/value, e.g. affinity { attribute = \"${meta.rack}\" } with no operand and weight, causing the inner validation error.","commonSituations":"Hand-writing affinity stanzas after the 0.11 spread/affinity feature introduction; confusing affinity syntax with constraint syntax; templated affinities emitting empty fields.","solutions":["Inspect the inner message after the colon for the specific field problem","Provide a valid operand (e.g. \"=\", \">\", \"regexp\") and required attribute/value fields","Validate locally with nomad job validate before submission"],"exampleFix":"// before\naffinity {\n  attribute = \"${meta.rack}\"\n  weight    = 50\n  # missing operand / RTarget\n}\n// after\naffinity {\n  attribute = \"${meta.rack}\"\n  operand   = \"=\"\n  value     = \"r1\"\n  weight    = 50\n}","handlingStrategy":"validation","validationCode":"for i, a := range tg.Affinities {\n    if err := a.Validate(); err != nil {\n        return fmt.Errorf(\"affinity %d: %w\", i+1, err)\n    }\n}","typeGuard":"func hasAffinityOperands(l, op, r string) bool { return l != \"\" && op != \"\" && r != \"\" }","tryCatchPattern":null,"preventionTips":["Mirror constraint syntax requirements in affinity stanzas (operand + value required)","Run nomad job validate before submitting","Don't reuse constraint snippets as affinities without checking required fields"],"tags":["nomad","affinity","validation","jobspec"],"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"}