{"id":"d6de1066b9220082","repo":"gohugoio/hugo","slug":"related-threshold-must-be-between-0-and-100","errorCode":null,"errorMessage":"related threshold must be between 0 and 100","messagePattern":"related threshold must be between 0 and 100","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"related/inverted_index.go","lineNumber":575,"sourceCode":"\n// DecodeConfig decodes a slice of map into Config.\nfunc DecodeConfig(m hmaps.Params) (Config, error) {\n\tif m == nil {\n\t\treturn Config{}, errors.New(\"no related config provided\")\n\t}\n\n\tif len(m) == 0 {\n\t\treturn Config{}, errors.New(\"empty related config provided\")\n\t}\n\n\tvar c Config\n\n\tif err := mapstructure.WeakDecode(m, &c); err != nil {\n\t\treturn c, err\n\t}\n\n\tif c.Threshold < 0 || c.Threshold > 100 {\n\t\treturn Config{}, errors.New(\"related threshold must be between 0 and 100\")\n\t}\n\n\tif c.ToLower {\n\t\tfor i := range c.Indices {\n\t\t\tc.Indices[i].ToLower = true\n\t\t}\n\t}\n\tfor i := range c.Indices {\n\t\t// Lower case name.\n\t\tc.Indices[i].Name = strings.ToLower(c.Indices[i].Name)\n\n\t\ticfg := c.Indices[i]\n\t\tif icfg.Type == \"\" {\n\t\t\tc.Indices[i].Type = TypeBasic\n\t\t}\n\t\tif !validTypes[c.Indices[i].Type] {\n\t\t\treturn c, fmt.Errorf(\"invalid index type %q. Must be one of %v\", c.Indices[i].Type, maps.Keys(validTypes))\n\t\t}","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/related/inverted_index.go#L557-L593","documentation":"After decoding the `related` config, Hugo validates that `threshold` — the minimum normalized match rank (0–100) a candidate page needs to count as related — lies in range (related/inverted_index.go:574). Values outside 0–100 are meaningless since ranks are normalized to that scale by norm().","triggerScenarios":"Site config with `related.threshold` set below 0 or above 100, e.g. `threshold = 120` or `threshold = -1`, caught in DecodeConfig at startup/config load.","commonSituations":"Treating threshold as an unbounded score or a fraction scaled wrong (e.g. entering 0.8 works, but 800 doesn't); copying values from other search tools that use different scales.","solutions":["Set `related.threshold` to a value between 0 and 100 (Hugo's default is 80).","Lower the threshold toward 0 to get more (looser) matches, raise toward 100 for stricter matching."],"exampleFix":"# before (hugo.toml)\n[related]\nthreshold = 120\n# after\n[related]\nthreshold = 80","handlingStrategy":"validation","validationCode":"# threshold is a percentage\n[related]\n  threshold = 80  # must be 0–100","typeGuard":"func validThreshold(t int) bool { return t >= 0 && t <= 100 }","tryCatchPattern":"if err := cfg.Validate(); err != nil {\n    return fmt.Errorf(\"fix related.threshold (0-100): %w\", err)\n}","preventionTips":["Treat `related.threshold` as a match percentage, 0–100 inclusive","Validate config-generation scripts so they can't emit negative or >100 thresholds"],"tags":["related-content","config","validation"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}