gohugoio/hugo · error
failed to decode languages config
Error message
failed to decode languages config: %w
What it means
Specific to the `languages` decoder (alldecoders.go:236). It calls langs.DecodeConfig, which mapstructure-decodes the languages map and then runs LanguagesInternal.init. init validates every language name is a non-empty valid identifier, that the configured defaultContentLanguage exists and is not disabled, and that disabled-language handling is consistent. Any of those produce a wrapped error here.
Solutions
- Confirm every `[languages.<key>]` uses a lowercase identifier matching a valid language code.
- Ensure `defaultContentLanguage` matches an existing, non-disabled language key.
- Remove any language listed in `disableLanguages` that is also the default, or change the default.
- Validate each language block's field types (weight is int, disabled is bool, etc.).
Example fix
# before defaultContentLanguage = "fr" [languages] [languages.en] weight = 1 # after defaultContentLanguage = "en" [languages] [languages.en] weight = 1
Defensive patterns
Strategy: validation
Validate before calling
# Verify every language key is a lowercase identifier and defaultContentLanguage matches
python3 - <<'PY'
import tomllib,re
cfg=tomllib.loads(open('hugo.toml').read())
langs=(cfg.get('languages') or {})
for k in langs:
assert re.fullmatch(r'[a-z][a-z0-9-]*',k), f"bad lang key {k!r}"
dcl=cfg.get('defaultContentLanguage')
if dcl: assert dcl in langs, f"defaultContentLanguage {dcl!r} not in languages"
print("languages ok")
PY Prevention
- Use lowercase BCP-47-ish identifiers for language keys.
- Keep defaultContentLanguage in sync with an existing, enabled language.
- Never list the default language in disableLanguages.
When it happens
Trigger: A language key that is empty or contains invalid characters (fails paths.ValidateIdentifier); setting `defaultContentLanguage = "fr"` when no `[languages.fr]` exists; marking the default language as `disabled = true`; a mapstructure decode failure because a language field has the wrong type.
Common situations: Renaming a language but forgetting to update defaultContentLanguage; using uppercase or punctuation in a language key; disabling the default language via disableLanguages flag while it remains the default; locale/languageCode mismatch resolved incorrectly.
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
- language name cannot be empty
- failed to decode config for language
- invalid language configuration for
- language not found
- config needs a filename
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/3580bb4e31908e5c.
Report an issue: GitHub.
Appendix: source
Thrown at config/allconfig/alldecoders.go:252
},
},
"languages": {
key: "languages",
decode: func(d decodeWeight, p decodeConfig) error {
m := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))
// Root-level locale/languageCode is passed to DecodeConfig so it can
// be applied to the default content language inside langs.DecodeConfig.
// They are passed separately so that an explicit per-lang languageCode
// can override a root-level languageCode (but not a root-level locale).
rootLocale := p.p.GetString("locale")
rootLanguageCode := p.p.GetString("languagecode")
var (
err error
defaultContentLanguage string
)
p.c.Languages, defaultContentLanguage, err = langs.DecodeConfig(p.c.RootConfig.DefaultContentLanguage, rootLocale, rootLanguageCode, p.c.RootConfig.DisableLanguages, m)
if err != nil {
return fmt.Errorf("failed to decode languages config: %w", err)
}
for k, v := range p.c.Languages.Config.LanguageConfigs {
if v.Disabled {
p.c.RootConfig.DisableLanguages = append(p.c.RootConfig.DisableLanguages, k)
}
}
p.c.RootConfig.DisableLanguages = hstrings.UniqueStringsReuse(p.c.RootConfig.DisableLanguages)
sort.Strings(p.c.RootConfig.DisableLanguages)
p.c.RootConfig.DefaultContentLanguage = defaultContentLanguage
return nil
},
},
"versions": {
key: "versions",
decode: func(d decodeWeight, p decodeConfig) error {
var err error
m := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))View on GitHub (pinned to 52c9bd7908)