{"record":{"id":"da111fb8c783e624","repo":"gohugoio/hugo","slug":"failed-to-decode-related-config-w","errorCode":null,"errorMessage":"failed to decode related config: %w","messagePattern":"failed to decode related config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/allconfig/alldecoders.go","lineNumber":360,"sourceCode":"\t\t\t\tfor k, v := range m {\n\t\t\t\t\tif k == \"\" || v == \"\" {\n\t\t\t\t\t\tdelete(m, k)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp.c.Taxonomies = m\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t},\n\t\"related\": {\n\t\tkey:    \"related\",\n\t\tweight: 100, // This needs to be decoded after taxonomies.\n\t\tdecode: func(d decodeWeight, p decodeConfig) error {\n\t\t\tif p.p.IsSet(d.key) {\n\t\t\t\tvar err error\n\t\t\t\tp.c.Related, err = related.DecodeConfig(p.p.GetParams(d.key))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to decode related config: %w\", err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tp.c.Related = related.DefaultConfig\n\t\t\t\tif _, found := p.c.Taxonomies[\"tag\"]; found {\n\t\t\t\t\tp.c.Related.Add(related.IndexConfig{Name: \"tags\", Weight: 80, Type: related.TypeBasic})\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t},\n\n\t\"cascade\": {\n\t\tkey: \"cascade\",\n\t\tdecode: func(d decodeWeight, p decodeConfig) error {\n\t\t\tvar err error\n\t\t\tp.c.Cascade, err = page.DecodeCascadeConfig(p.p.Get(d.key))\n\t\t\treturn err\n\t\t},","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/config/allconfig/alldecoders.go#L342-L378","documentation":"Specific to the `related` decoder (alldecoders.go:352), which only runs when a `[related]` section is present. It calls related.DecodeConfig, which rejects: nil/empty related config, threshold outside 0-100, an invalid index `type` (must be a known type), and cardinalityThreshold outside 0-100. Each becomes the wrapped cause.","triggerScenarios":"Providing `[related]` as an empty table; setting `threshold = 150` or a negative; declaring an index with `type = \"fuzzy\"` (not a valid type); setting an index `cardinalityThreshold` outside 0-100.","commonSituations":"Copying a related config from an old Hugo version where valid types differed; partially editing a working related config and leaving an empty body; misreading docs and using an unsupported index type.","solutions":["Set `threshold` between 0 and 100 inclusive.","Use only valid index types: the wrapped error lists them via maps.Keys(validTypes).","If you don't need a custom related config, delete the `[related]` section to use the default (auto-adds a tags index).","Ensure each `[[related.indices]]` has a `name` and a valid `type`."],"exampleFix":"# before\n[related]\nthreshold = 120\n[[related.indices]]\nname = \"tags\"\ntype = \"fuzzy\"\n\n# after\n[related]\nthreshold = 80\n[[related.indices]]\nname = \"tags\"\nweight = 80\ntype = \"basic\"","handlingStrategy":"validation","validationCode":"python3 - <<'PY'\nimport tomllib\ncfg=tomllib.loads(open('hugo.toml').read())\nr=cfg.get('related')\nif r is not None:\n    assert r, \"related section is empty\"\n    assert 0<=r.get('threshold',0)<=100, \"threshold out of range\"\n    valid={'basic'}\n    for idx in r.get('indices',[]):\n        t=idx.get('type','basic')\n        assert t in valid, f\"invalid index type {t!r}\"\nprint(\"related ok\")\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit `[related]` entirely if defaults suffice (tags index auto-added).","Keep threshold and cardinalityThreshold within 0-100.","Use only documented index types; check docs after Hugo upgrades."],"tags":["config","related","search","validation"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}