gohugoio/hugo · error
failed to decode
Error message
failed to decode %q: %w
What it means
Generic decoder-level error emitted by decodeConfigFromParams. It runs each registered section decoder (an entry in allDecoderSetups: build, languages, markup, mediatypes, outputformats, caches, etc.) in dependency order. When any single decoder returns an error, it is wrapped with that decoder's key so you know which top-level config section failed. This is the common ancestor of the more specific "failed to decode languages config" and "failed to decode related config" errors.
Solutions
- The wrapped error and the quoted key identify the failing section. Open that section and validate field types against current Hugo docs.
- Run `hugo config` to see how far decoding got before failing.
- Comment out the named section; if the build proceeds, the problem is isolated to it.
- Compare the section against a freshly generated `hugo new site` default.
Example fix
# before (outputformats missing isPlainText) [outputFormats.MYFORMAT] mediaType = "text/html" # after [outputFormats.MYFORMAT] mediaType = "text/html" isPlainText = true
Defensive patterns
Strategy: validation
Validate before calling
# Lint config files for syntax before running hugo
# TOML:
python -c "import tomllib,sys; tomllib.loads(open('hugo.toml').read())" 2>&1 || echo "TOML invalid"
# YAML:
python -c "import yaml,sys; yaml.safe_load(open('config.yaml'))" 2>&1 || echo "YAML invalid" Prevention
- Add a config-syntax lint step to CI before `hugo build`.
- After upgrading Hugo, run `hugo config` and resolve any renamed/retyped fields.
- Start from a known-good `hugo new site` config and add sections incrementally.
When it happens
Trigger: Any malformed top-level config section: a `[build]` map with wrong field types, a `[markup]` sub-map that fails mapstructure decode, an `[outputformats]` entry missing a required field, a `[mediatypes]` entry with a bad suffix. Also reached via the per-language re-decode path.
Common situations: Typo in a config key; upgrading Hugo and a config field changed type or was renamed; pasting example config from an incompatible Hugo version; TOML/YAML/JSON syntax that parses but yields wrong-typed values.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to create config from modules config
- failed to create config from result
- failed to decode config for language
- failed to decode filecache config
- failed to decode output format configuration
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/16cc1c1adcec91ec.
Report an issue: GitHub.
Appendix: source
Thrown at config/allconfig/allconfig.go:1218
} else {
logger.Warnf("Skip unknown config key %q", key)
}
}
}
// Sort them to get the dependency order right.
sort.Slice(decoderSetups, func(i, j int) bool {
ki, kj := decoderSetups[i], decoderSetups[j]
if ki.weight == kj.weight {
return ki.key < kj.key
}
return ki.weight < kj.weight
})
for _, v := range decoderSetups {
p := decodeConfig{p: p, c: target, fs: fs, bcfg: bcfg, logger: logger}
if err := v.decode(v, p); err != nil {
return fmt.Errorf("failed to decode %q: %w", v.key, err)
}
}
return nil
}
func createDefaultOutputFormats(allFormats output.Formats) map[string][]string {
if len(allFormats) == 0 {
panic("no output formats")
}
rssOut, rssFound := allFormats.GetByName(output.RSSFormat.Name)
htmlOut, _ := allFormats.GetByName(output.HTMLFormat.Name)
defaultListTypes := []string{htmlOut.Name}
if rssFound {
defaultListTypes = append(defaultListTypes, rssOut.Name)
}
View on GitHub (pinned to 52c9bd7908)