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

  1. Read the wrapped error: it names the decoder key (e.g. "markup") and the real cause. Fix that field in the offending language block.
  2. Temporarily reduce the failing language block to empty `{}` and re-add keys one by one to isolate the offending field.
  3. Diff the failing language block against the `en`/root block to spot type or key mismatches.
  4. 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

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

Related errors


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)