gohugoio/hugo · error

invalid index type . Must be one of

Error message

invalid index type %q. Must be one of %v

What it means

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.

Solutions

  1. Set the index type to "basic" (default for keyword/date indices) or "fragments" (for heading-fragment matching).
  2. Omit the type field entirely -- DecodeConfig defaults empty to "basic".
  3. Check the error message: it prints the accepted map keys.

Example fix

// before
[[related.indices]]
name = "tags"
type = "fragment"
weight = 100

// after
type = "fragments"
Defensive patterns

Strategy: validation

Validate before calling

var validRelatedTypes = map[string]bool{"basic": true, "fragments": true}
func validateIndexTypes(cfg related.Config) error {
    for _, i := range cfg.Indices {
        t := i.Type
        if t == "" { t = "basic" }
        if !validRelatedTypes[t] {
            return fmt.Errorf("index %q has invalid type %q", i.Name, i.Type)
        }
    }
    return nil
}

Type guard

func isValidRelatedType(t string) bool {
    t = strings.ToLower(strings.TrimSpace(t))
    if t == "" { t = "basic" }
    return t == "basic" || t == "fragments"
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/2ed63343728907ef. Report an issue: GitHub.

Appendix: source

Thrown at related/inverted_index.go:592

	if c.Threshold < 0 || c.Threshold > 100 {
		return Config{}, errors.New("related threshold must be between 0 and 100")
	}

	if c.ToLower {
		for i := range c.Indices {
			c.Indices[i].ToLower = true
		}
	}
	for i := range c.Indices {
		// Lower case name.
		c.Indices[i].Name = strings.ToLower(c.Indices[i].Name)

		icfg := c.Indices[i]
		if icfg.Type == "" {
			c.Indices[i].Type = TypeBasic
		}
		if !validTypes[c.Indices[i].Type] {
			return c, fmt.Errorf("invalid index type %q. Must be one of %v", c.Indices[i].Type, maps.Keys(validTypes))
		}
		if icfg.CardinalityThreshold < 0 || icfg.CardinalityThreshold > 100 {
			return Config{}, errors.New("cardinalityThreshold threshold must be between 0 and 100")
		}
	}

	return c, nil
}

// StringKeyword is a string search keyword.
type StringKeyword string

func (s StringKeyword) String() string {
	return string(s)
}

// FragmentKeyword represents a document fragment.
type FragmentKeyword string

View on GitHub (pinned to 52c9bd7908)