gohugoio/hugo · error
failed to decode build config in front matter: %s%s
Error message
failed to decode build config in front matter: %s%s
What it means
Hugo failed to decode the `build` (or legacy `_build`) front matter key into its pagemeta.BuildConfig struct (fields like render, list, publishResources). Since Hugo 0.123.0 `build` is a reserved front matter keyword, so any value that isn't a valid build-options map fails decoding. The extra message detail is appended only for the new `build` keyword to warn users who used `build` as a personal param.
Source
Thrown at hugolib/page__meta.go:671
} else {
buildConfig = pcfg.Params["build"]
isNewBuildKeyword = true
}
pm.pageConfig.Build, err = pagemeta.DecodeBuildConfig(buildConfig)
if err != nil {
var msgDetail string
if isNewBuildKeyword {
msgDetail = `. We renamed the _build keyword to build in Hugo 0.123.0. We recommend putting user defined params in the params section, e.g.:
---
title: "My Title"
params:
build: "My Build"
---
´
`
}
return fmt.Errorf("failed to decode build config in front matter: %s%s", err, msgDetail)
}
var draft, published, isCJKLanguage *bool
var userParams map[string]any
for k, v := range pcfg.Params {
loki := strings.ToLower(k)
if loki == "params" {
vv, err := hmaps.ToParamsAndPrepare(v)
if err != nil {
return fmt.Errorf("front matter field %q must be a map: %w", k, err)
}
userParams = vv
delete(pcfg.Params, k)
continue
}
if loki == "published" { // Intentionally undocumentedView on GitHub ↗ (pinned to 8a468df065)
Solutions
- If `build` was your own custom param, move it under the `params:` section of front matter (`params:\n build: ...`) and access it via .Params.build.
- If you intend Hugo build options, make it a map with valid keys/values: `build:\n render: never\n list: local\n publishResources: false`.
- Migrate any remaining `_build` keys to `build` (the old key is deprecated since 0.145.0).
Example fix
# before --- title: "My Title" build: "My Build" --- # after --- title: "My Title" params: build: "My Build" ---
Defensive patterns
Strategy: validation
Validate before calling
// Validate front matter 'build' before creating the page
if b, ok := fm["build"]; ok {
if _, ok := b.(map[string]any); !ok {
return fmt.Errorf("build must be a map, got %T", b)
}
} Type guard
func isMap(v any) bool {
_, ok := v.(map[string]any)
return ok
} Try / catch
if err := site.Build(); err != nil {
if strings.Contains(err.Error(), "failed to decode build config") {
// report offending page's front matter to the author
}
return err
} Prevention
- Keep the front matter `build` key a map with only documented fields (render, list, publishResources)
- Lint front matter with a YAML/TOML schema in CI before running hugo
- Don't reuse the reserved key `build` for custom page params — put custom data under `params`
When it happens
Trigger: A page's front matter contains `build:` (or deprecated `_build:`) with a value that pagemeta.DecodeBuildConfig cannot map — e.g. a string (`build: "My Build"`), a list, or a map with wrongly-typed fields such as `render: 5` instead of one of never/always/link.
Common situations: Most common after upgrading past Hugo 0.123.0: sites that used `build` as a user-defined param (e.g. a build number or CI tag) at the top level of front matter suddenly break, because `_build` was renamed to `build` and now collides. Also typos inside legitimate build option maps.
Related errors
- media type %q not found
- key %q not allowed in cascade config
- failed to decode sitemap config in front matter: %s
- unable to cast %#v of type %T to []map[string]interface{}
- language %q not found
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/a0f1079e32abd1e3.json.
Report an issue: GitHub ↗.