gohugoio/hugo · error

failed to decode %q: %w

Error message

failed to decode %q: %w

What it means

Raised in decodeConfigFromParams (allconfig.go:1218) when a single config section's decoder fails; v.key is the section name (e.g. "markup", "outputs", "imaging", "languages"). Hugo decodes the raw config map section-by-section via registered decodeWeight setups in dependency order, and wraps the first decoder failure with its section key so the user knows which top-level block is malformed.

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 8a468df065)

Solutions

  1. Identify the section from the quoted key in the message and inspect the wrapped inner error for the exact field.
  2. Compare the section against the current Hugo docs schema for that key; fix types (map vs list vs scalar).
  3. Bisect by commenting out the named section to confirm, then reintroduce fields incrementally.
  4. If the error appeared after a Hugo upgrade, check the release notes for config schema changes in that section.

Example fix

# before
[imaging]
quality = "high"
# after
[imaging]
quality = 75
Defensive patterns

Strategy: validation

Validate before calling

// The error names the config section that failed to decode.
// Pre-check top-level sections are tables of the expected shape:
known := map[string]bool{"params": true, "markup": true, "outputs": true /* ... */}
for k, v := range rootCfg {
    if known[k] {
        if _, ok := v.(map[string]any); !ok && k != "outputs" {
            return fmt.Errorf("%q must be a table, got %T", k, v)
        }
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to decode") {
    // The %q in the message names the offending section (e.g. "markup", "outputs")
    return fmt.Errorf("fix the named config section's structure/types, then reload: %w", err)
}

Prevention

When it happens

Trigger: Any top-level config section whose structure fails mapstructure decoding or the section's own validation — e.g. invalid `imaging.quality` out of range, malformed `outputFormats`, invalid `permalinks` patterns, bad `security` policy values, or wrong types anywhere in a known section.

Common situations: Typos and wrong value types after hand-editing hugo.toml/yaml, upgrading Hugo across versions where a section's schema changed (e.g. markup, pagination), or merging theme example configs with incompatible structures.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/16cc1c1adcec91ec.json. Report an issue: GitHub ↗.