{"record":{"id":"3580bb4e31908e5c","repo":"gohugoio/hugo","slug":"failed-to-decode-languages-config-w","errorCode":null,"errorMessage":"failed to decode languages config: %w","messagePattern":"failed to decode languages config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/allconfig/alldecoders.go","lineNumber":252,"sourceCode":"\t\t},\n\t},\n\t\"languages\": {\n\t\tkey: \"languages\",\n\t\tdecode: func(d decodeWeight, p decodeConfig) error {\n\t\t\tm := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))\n\t\t\t// Root-level locale/languageCode is passed to DecodeConfig so it can\n\t\t\t// be applied to the default content language inside langs.DecodeConfig.\n\t\t\t// They are passed separately so that an explicit per-lang languageCode\n\t\t\t// can override a root-level languageCode (but not a root-level locale).\n\t\t\trootLocale := p.p.GetString(\"locale\")\n\t\t\trootLanguageCode := p.p.GetString(\"languagecode\")\n\t\t\tvar (\n\t\t\t\terr                    error\n\t\t\t\tdefaultContentLanguage string\n\t\t\t)\n\t\t\tp.c.Languages, defaultContentLanguage, err = langs.DecodeConfig(p.c.RootConfig.DefaultContentLanguage, rootLocale, rootLanguageCode, p.c.RootConfig.DisableLanguages, m)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to decode languages config: %w\", err)\n\t\t\t}\n\t\t\tfor k, v := range p.c.Languages.Config.LanguageConfigs {\n\t\t\t\tif v.Disabled {\n\t\t\t\t\tp.c.RootConfig.DisableLanguages = append(p.c.RootConfig.DisableLanguages, k)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tp.c.RootConfig.DisableLanguages = hstrings.UniqueStringsReuse(p.c.RootConfig.DisableLanguages)\n\t\t\tsort.Strings(p.c.RootConfig.DisableLanguages)\n\t\t\tp.c.RootConfig.DefaultContentLanguage = defaultContentLanguage\n\t\t\treturn nil\n\t\t},\n\t},\n\t\"versions\": {\n\t\tkey: \"versions\",\n\t\tdecode: func(d decodeWeight, p decodeConfig) error {\n\t\t\tvar err error\n\t\t\tm := hmaps.CleanConfigStringMap(p.p.GetStringMap(d.key))","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/config/allconfig/alldecoders.go#L234-L270","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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.)."],"exampleFix":"# before\ndefaultContentLanguage = \"fr\"\n[languages]\n[languages.en]\nweight = 1\n\n# after\ndefaultContentLanguage = \"en\"\n[languages]\n[languages.en]\nweight = 1","handlingStrategy":"validation","validationCode":"# Verify every language key is a lowercase identifier and defaultContentLanguage matches\npython3 - <<'PY'\nimport tomllib,re\ncfg=tomllib.loads(open('hugo.toml').read())\nlangs=(cfg.get('languages') or {})\nfor k in langs:\n    assert re.fullmatch(r'[a-z][a-z0-9-]*',k), f\"bad lang key {k!r}\"\ndcl=cfg.get('defaultContentLanguage')\nif dcl: assert dcl in langs, f\"defaultContentLanguage {dcl!r} not in languages\"\nprint(\"languages ok\")\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["config","i18n","languages","validation"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}