{"record":{"id":"2ed63343728907ef","repo":"gohugoio/hugo","slug":"invalid-index-type-q-must-be-one-of-v","errorCode":null,"errorMessage":"invalid index type %q. Must be one of %v","messagePattern":"invalid index type %q\\. Must be one of (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"related/inverted_index.go","lineNumber":592,"sourceCode":"\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}\n\t\tif icfg.CardinalityThreshold < 0 || icfg.CardinalityThreshold > 100 {\n\t\t\treturn Config{}, errors.New(\"cardinalityThreshold threshold must be between 0 and 100\")\n\t\t}\n\t}\n\n\treturn c, nil\n}\n\n// StringKeyword is a string search keyword.\ntype StringKeyword string\n\nfunc (s StringKeyword) String() string {\n\treturn string(s)\n}\n\n// FragmentKeyword represents a document fragment.\ntype FragmentKeyword string","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/related/inverted_index.go#L574-L610","documentation":"Returned by related.DecodeConfig when an IndexConfig.Type is neither \"basic\" nor \"fragments\" (the only entries in validTypes). After defaulting an empty Type to \"basic\", any remaining unrecognised value is rejected. The error lists the valid type keys so the developer knows the accepted set.","triggerScenarios":"Setting [[related.indices]] type = \"fulltext\" (or any string other than basic/fragments) in hugo.toml. DecodeConfig runs at site config load, so this fails during Hugo startup before any build.","commonSituations":"Typing the index type (e.g. \"fragment\" singular, \"semantic\", \"text\"); assuming a type exists that this Hugo version does not support; copying config from a newer/older Hugo with different supported types.","solutions":["Set the index type to \"basic\" (default for keyword/date indices) or \"fragments\" (for heading-fragment matching).","Omit the type field entirely -- DecodeConfig defaults empty to \"basic\".","Check the error message: it prints the accepted map keys."],"exampleFix":"// before\n[[related.indices]]\nname = \"tags\"\ntype = \"fragment\"\nweight = 100\n\n// after\ntype = \"fragments\"","handlingStrategy":"validation","validationCode":"var validRelatedTypes = map[string]bool{\"basic\": true, \"fragments\": true}\nfunc validateIndexTypes(cfg related.Config) error {\n    for _, i := range cfg.Indices {\n        t := i.Type\n        if t == \"\" { t = \"basic\" }\n        if !validRelatedTypes[t] {\n            return fmt.Errorf(\"index %q has invalid type %q\", i.Name, i.Type)\n        }\n    }\n    return nil\n}","typeGuard":"func isValidRelatedType(t string) bool {\n    t = strings.ToLower(strings.TrimSpace(t))\n    if t == \"\" { t = \"basic\" }\n    return t == \"basic\" || t == \"fragments\"\n}","tryCatchPattern":null,"preventionTips":["Use only \"basic\" or \"fragments\" for index types.","Omit type to default to \"basic\".","Validate config in CI with a lint step before building."],"tags":["related","config","validation","index-type"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}