gohugoio/hugo · error

cardinalityThreshold threshold must be between 0 and 100

Error message

cardinalityThreshold threshold must be between 0 and 100

What it means

Hugo's related-content system builds an inverted index to find related pages. Each configured index may set a `cardinalityThreshold`, a percentage (0-100) that filters out overly common keywords (e.g. 50 drops keywords used in >50% of documents). `DecodeConfig` in related/inverted_index.go rejects any index whose threshold is negative or above 100, because a percentage outside that range is meaningless.

Solutions

  1. Set cardinalityThreshold to an integer between 0 and 100 inclusive in the offending [related.indices] entry.
  2. If unsure what value to use, omit the field entirely so it defaults to 0 (no keyword filtering).
  3. Audit every [related.indices] block, not just the first — the loop validates each one.

Example fix

# before
[related.indices]
name = "tags"
weight = 100
cardinalityThreshold = 150

# after
[related.indices]
name = "tags"
weight = 100
cardinalityThreshold = 50
Defensive patterns

Strategy: validation

Validate before calling

// Validate each related index before relying on DecodeConfig
for _, idx := range cfg.Indices {
    if idx.CardinalityThreshold < 0 || idx.CardinalityThreshold > 100 {
        return fmt.Errorf("index %q: cardinalityThreshold must be 0-100, got %d", idx.Name, idx.CardinalityThreshold)
    }
}

Prevention

When it happens

Trigger: Setting `cardinalityThreshold` to a value < 0 or > 100 under any `[related.indices]` entry in hugo.toml/yaml/json. Triggered during site build when the related config is decoded (inverted_index.go:594).

Common situations: Confusing `cardinalityThreshold` (a 0-100 percentage) with `weight` (uncapped integer); copy-pasting a tutorial value out of range; migrating from older Hugo related config; typo such as a stray minus sign or extra digit.

Related errors


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

Appendix: source

Thrown at related/inverted_index.go:595

	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

func (f FragmentKeyword) String() string {
	return string(f)

View on GitHub (pinned to 52c9bd7908)