gohugoio/hugo · error
failed to decode config for language
Error message
failed to decode config for language %q: %w
What it means
Thrown while building per-language Config clones during multilingual setup. After root-level config is decoded, fromLoadConfigResult iterates each entry in `languages`, clones the merged config, and re-runs the section decoders only for the keys that differ from root. If any of those per-language section decoders (build, markup, outputformats, etc.) fails, the failure is wrapped with the language key (e.g. "en", "fr"). It tells you WHICH language broke decoding, while the wrapped cause tells you which section/field.
Solutions
- Read the wrapped error: it names the decoder key (e.g. "markup") and the real cause. Fix that field in the offending language block.
- Temporarily reduce the failing language block to empty `{}` and re-add keys one by one to isolate the offending field.
- Diff the failing language block against the `en`/root block to spot type or key mismatches.
- Run `hugo config --lang <k>` to print the decoded config for that language and inspect what differs.
Example fix
# before
[languages.fr]
weight = 20
[languages.fr.markup.goldmark.parser]
attribute = "notabool" # wrong type
# after
[languages.fr]
weight = 20
[languages.fr.markup.goldmark.parser]
attribute = { title = "" } # correct map type Defensive patterns
Strategy: validation
Validate before calling
# Before running hugo, validate each language block decodes by type-checking
# key fields against root. Quick shell check for common type mistakes:
for lang in $(hugo config --renderToMemory 2>/dev/null | awk -F. '/^languages\./{print $2}' | sort -u); do
echo "checking $lang"
hugo config --lang "$lang" >/dev/null || echo "FAIL: $lang"
done Prevention
- Keep language blocks structurally identical to the root/default language; only override scalar values.
- When adding a new language, copy the entire default-language block and edit values rather than writing from scratch.
- Run `hugo config --lang <k>` in CI for every language to catch per-language decode failures early.
When it happens
Trigger: A multilingual site where one language block under [[languages.fr]] or [languages.fr.markup] contains a structurally invalid value (wrong type, unknown enum, malformed sub-map). Only happens when a language overrides a root key that is a Params map, forcing re-decode via decodeConfigFromParams in allconfig.go:1140.
Common situations: Copying an `en` language block to `fr` and leaving a field that only validates in one locale (e.g. a bad `markup.goldmark.parser` map); setting a language-specific `outputformats` or `mediaTypes` entry with a malformed shape; YAML indentation drift when a new language is added.
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 decode languages config
- invalid language configuration for
- language name cannot be empty
- failed to create config from modules config
- failed to create config from result
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/9febc21d96b7dcdd.
Report an issue: GitHub.
Appendix: source
Thrown at config/allconfig/allconfig.go:1141
differentRootKeys = append(differentRootKeys, kk)
default:
// Apply new values to the root.
differentRootKeys = append(differentRootKeys, "")
}
}
}
differentRootKeys = hstrings.UniqueStringsSorted(differentRootKeys)
if len(differentRootKeys) == 0 {
langConfigMap[k] = all
continue
}
// Create a copy of the complete config and replace the root keys with the language specific ones.
clone := all.cloneForLang()
if err := decodeConfigFromParams(fs, logger, bcfg, mergedConfig, clone, differentRootKeys); err != nil {
return nil, fmt.Errorf("failed to decode config for language %q: %w", k, err)
}
if err := clone.CompileConfig(logger); err != nil {
return nil, err
}
// Adjust Goldmark config defaults for multilingual, single-host sites.
if len(languagesConfig) > 1 && !isMultihost && !clone.Markup.Goldmark.DuplicateResourceFiles {
if clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedFallback
}
if clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedFallback
}
}
langConfigMap[k] = clone
case hmaps.ParamsMergeStrategy:
View on GitHub (pinned to 52c9bd7908)