{"record":{"id":"703c334b59268c37","repo":"hashicorp/nomad","slug":"spread-block-must-have-a-positive-weight-from-0-to","errorCode":null,"errorMessage":"Spread block must have a positive weight from 0 to 100","messagePattern":"Spread block must have a positive weight from 0 to 100","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":10329,"sourceCode":"\tns.SpreadTarget = CopySliceSpreadTarget(s.SpreadTarget)\n\treturn ns\n}\n\nfunc (s *Spread) String() string {\n\tif s.str != \"\" {\n\t\treturn s.str\n\t}\n\ts.str = fmt.Sprintf(\"%s %s %v\", s.Attribute, s.SpreadTarget, s.Weight)\n\treturn s.str\n}\n\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 {","sourceCodeStart":10311,"sourceCodeEnd":10347,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L10311-L10347","documentation":"Spread.Validate() requires Weight to be strictly greater than 0 and at most 100. When Weight is zero, negative, or above 100, this error is appended. The weight determines how strongly spread scoring influences placement relative to other scoring factors, so it must fit in the 1-100 range.","triggerScenarios":"Submitting a spread stanza with weight = 0 (or omitted where defaulting didn't apply) or weight = 150; constructing Spread{Attribute: ..., Weight: 0} in Go before Validate.","commonSituations":"Users thinking 0 weight means 'disabled' and setting weight = 0 (they should delete the stanza instead); percentage confusion where users pass 0-1 floats; programmatic generation defaulting to Go zero-value 0.","solutions":["Set weight to an integer between 1 and 100, e.g. weight = 50.","If you meant to disable spreading, remove the spread stanza entirely instead of using weight = 0.","If computing weight dynamically, clamp it: w := min(max(w, 1), 100) before constructing Spread.","Validate the job with `nomad job validate` first."],"exampleFix":"// before\nspread {\n  attribute = \"${node.datacenter}\"\n  weight    = 0\n}\n// after\nspread {\n  attribute = \"${node.datacenter}\"\n  weight    = 50\n}","handlingStrategy":"validation","validationCode":"func validateSpreadWeight(s *structs.Spread) error {\n\tif s.Weight <= 0 || s.Weight > 100 {\n\t\treturn fmt.Errorf(\"spread weight must be in (0, 100], got %d\", s.Weight)\n\t}\n\treturn nil\n}","typeGuard":"func validSpreadWeight(w uint8) bool { return w > 0 && w <= 100 }","tryCatchPattern":null,"preventionTips":["Remember weight is an integer 1-100, not a 0-1 float.","Use weight = 0 never; delete the spread stanza to disable spreading.","Clamp programmatically computed weights into [1, 100]."],"tags":["nomad","spread","scheduling","validation","range-check"],"backgroundTag":"value-out-of-range","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"}