gohugoio/hugo · error

failed to decode sites from front matter

Error message

failed to decode sites from front matter: %w

What it means

Thrown while decoding the optional 'sites' front matter key into the sitesmatrix.Sites struct via mapstructure.WeakDecode. The wrapped error is the underlying decode failure, so the front matter 'sites' block could not be coerced into the expected matrix/complements shape.

Solutions

  1. Check the wrapped error message for the exact mapstructure field that failed.
  2. Format the 'sites' front matter key per the sitesmatrix spec (matrix/complements glob maps).
  3. Remove the 'sites' key entirely if you do not need multi-site routing; Hugo will fall back to the site default.

Example fix

# before
---
sites: en
---
# after (or omit it)
---
sites:
  matrix:
    language: en
---
Defensive patterns

Strategy: validation

Validate before calling

if v, found := fm["sites"]; found {
    if err := mapstructure.WeakDecode(v, &target); err != nil {
        return fmt.Errorf("bad sites front matter: %w", err)
    }
}

Try / catch

if err := pcfg.SetMetaPreFromMap(ext, fm, logger, conf); err != nil {
    logger.Errorf("front matter sites invalid in %s: %v", path, err)
}

Prevention

When it happens

Trigger: A content file (or content-adapter map) sets a 'sites:' front matter key to a value whose structure does not match sitesmatrix.Sites, e.g. a bare string, a list of scalars, or a map with unrecognized fields.

Common situations: Authors misunderstand the multi-site/matrix feature and write 'sites: en' or 'sites: [en, fr]' instead of the matrix glob format. Also occurs after a Hugo upgrade that changed the 'sites' schema.

Understand the failure class

Related errors


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

Appendix: source

Thrown at resources/page/pagemeta/page_frontmatter.go:116

		if err := pcfg.setFromFrontMatter(frontmatter); err != nil {
			return err
		}
	}
	return pcfg.resolveContentType(ext, conf.GetConfigSection("mediaTypes").(media.Types))
}

func (pcfg *PageConfigEarly) setFromFrontMatter(frontmatter map[string]any) error {
	// Needed for case insensitive fetching of params values.
	hmaps.PrepareParams(frontmatter)
	pcfg.Frontmatter = frontmatter

	if v, found := frontmatter[pageMetaKeyMarkup]; found {
		pcfg.Content.Markup = cast.ToString(v)
	}

	if v, found := frontmatter[pageMetaKeySites]; found {
		if err := mapstructure.WeakDecode(v, &pcfg.Sites); err != nil {
			return fmt.Errorf("failed to decode sites from front matter: %w", err)
		}
	}
	return nil
}

func (p *PageConfigEarly) setCascadeEarlyValueIfNotSet(key string, value any) (done bool) {
	switch key {
	case pageMetaKeySites:
		p.Sites.SetFromParamsIfNotSet(value.(hmaps.Params))
	}

	return !p.Sites.Matrix.IsZero()
}

// Page config that needs to be set early.
type PageConfigEarly struct {
	Kind            string // The kind of page, e.g. "page", "section", "home" etc. This is usually derived from the content path.
	Path            string // The canonical path to the page, e.g. /sect/mypage. Note: Leading slash, no trailing slash, no extensions or language identifiers.

View on GitHub (pinned to 52c9bd7908)