gohugoio/hugo · error

failed to decode media types: %w

Error message

failed to decode media types: %w

What it means

This is the wrapping error returned when Hugo fails to decode the contentTypes config namespace. The underlying cause (%w) is either a structural decode failure (the section isn't a map, or a value can't be weak-decoded into ContentTypeConfig) or the 'unknown media type' validation error from the same buildConfig function. It surfaces at config load, halting the build.

Source

Thrown at media/config.go:216

			}
		}

		for k := range s {
			mediaType, found := types.GetByType(k)
			if !found {
				return c, nil, fmt.Errorf("unknown media type %q", k)
			}
			c.types = append(c.types, mediaType)
		}

		c.init(types)

		return c, s, nil
	}

	ns, err := config.DecodeNamespace[map[string]ContentTypeConfig](in, buildConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to decode media types: %w", err)
	}
	return ns, nil
}

// DecodeTypes decodes the given map of media types.
func DecodeTypes(in map[string]any) (*config.ConfigNamespace[map[string]MediaTypeConfig, Types], error) {
	buildConfig := func(v any) (Types, any, error) {
		m, err := hmaps.ToStringMapE(v)
		if err != nil {
			return nil, nil, err
		}
		if m == nil {
			m = map[string]any{}
		}
		m = hmaps.CleanConfigStringMap(m)
		// Merge with defaults.
		hmaps.MergeShallow(m, defaultMediaTypesConfig)

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Read the wrapped error after the colon — it names the exact cause (often 'unknown media type ...') and fix that.
  2. Ensure contentTypes is a map of MIME-string keys to tables, matching the documented shape.
  3. Validate the merged config with 'hugo config' to spot values injected by themes or modules.

Example fix

# before (hugo.yaml)
contentTypes: text/markdown

# after
contentTypes:
  text/markdown: {}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure mediaTypes config values are tables/maps, not scalars
for k, v := range cfg.GetStringMap("mediaTypes") {
    if _, ok := v.(map[string]any); !ok {
        return fmt.Errorf("mediaTypes.%s must be a table, got %T", k, v)
    }
}

Try / catch

conf, err := allconfig.LoadConfig(...)
if err != nil {
    // wrapped error chain: use errors.Unwrap / %+v to find the offending key
    log.Fatalf("config decode failed: %+v", err)
}

Prevention

When it happens

Trigger: config.DecodeNamespace failing while building ContentTypes: passing a non-map value for contentTypes, a value that mapstructure.WeakDecode cannot coerce into ContentTypeConfig, or an unregistered media-type key (which produces error 391 as the wrapped cause).

Common situations: Malformed contentTypes section in hugo.toml/yaml/json (e.g. a string or array where a table/map is expected); wrong nesting of keys; unknown media type keys; merging config from themes/modules where types conflict.

Related errors


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