{"record":{"id":"e5e52113897c983d","repo":"hashicorp/nomad","slug":"spread-target-value-q-already-defined","errorCode":null,"errorMessage":"Spread target value %q already defined","messagePattern":"Spread target value %q already defined","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10340,"sourceCode":"\nfunc (s *Spread) Validate() error {\n\tvar mErr multierror.Error\n\tif s.Attribute == \"\" {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Missing spread attribute\"))\n\t}\n\tif s.Weight <= 0 || s.Weight > 100 {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"Spread block must have a positive weight from 0 to 100\"))\n\t}\n\tseen := make(map[string]struct{})\n\tsumPercent := uint32(0)\n\n\tfor _, target := range s.SpreadTarget {\n\t\t// Make sure there are no duplicates\n\t\t_, ok := seen[target.Value]\n\t\tif !ok {\n\t\t\tseen[target.Value] = struct{}{}\n\t\t} else {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Spread target value %q already defined\", target.Value))\n\t\t}\n\t\tif target.Percent > 100 {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Spread target percentage for value %q must be between 0 and 100\", target.Value))\n\t\t}\n\t\tsumPercent += uint32(target.Percent)\n\t}\n\tif sumPercent > 100 {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Sum of spread target percentages must not be greater than 100%%; got %d%%\", sumPercent))\n\t}\n\treturn mErr.ErrorOrNil()\n}\n\n// SpreadTarget is used to specify desired percentages for each attribute value\ntype SpreadTarget struct {\n\t// Value is a single attribute value, like \"dc1\"\n\tValue string\n\n\t// Percent is the desired percentage of allocs","sourceCodeStart":10322,"sourceCodeEnd":10358,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10322-L10358","documentation":"Spread.Validate() checks that each Value in the spread's SpreadTarget list is unique. If the same target value appears more than once, Nomad rejects the job with 'Spread target value %q already defined'. Duplicate targets would double-count percentages and make scheduling weights ambiguous.","triggerScenarios":"Registering a job whose spread block lists two spread stanzas (or API SpreadTarget entries) with the same value, e.g. value = \"dc1\" twice, at job submission time.","commonSituations":"HCL with repeated spread target stanzas after copy-paste, merged/concatenated generated job specs, or templating loops that emit the same value twice.","solutions":["Remove or merge the duplicate spread target entries so each value appears once.","Combine the percentages of duplicates into a single target (respecting the 100% sum limit).","Deduplicate values programmatically before rendering the job spec."],"exampleFix":"// before\nspread {\n  attribute = \"${node.datacenter}\"\n  target \"dc1\" { percent = 30 }\n  target \"dc1\" { percent = 20 }\n}\n// after\nspread {\n  attribute = \"${node.datacenter}\"\n  target \"dc1\" { percent = 50 }\n}","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, t := range spread.SpreadTarget {\n  if seen[t.Value] { return fmt.Errorf(\"duplicate spread target %q\", t.Value) }\n  seen[t.Value] = true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deduplicate spread targets before rendering job HCL","Merge duplicate targets' percentages instead of listing twice","Review copy-pasted spread stanzas for repeated values"],"tags":["nomad","spread","job-spec","validation"],"backgroundTag":"duplicate-key","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"}