gohugoio/hugo · error

permalinks: unsupported config type %T

Error message

permalinks: unsupported config type %T

What it means

Thrown by DecodePermalinksConfig when the raw permalinks config value is neither a map[string]any / hmaps.Params (legacy map format) nor convertible to []map[string]any (new slice format). It reports the concrete type, meaning the config shape itself is unrecognizable.

Solutions

  1. Provide permalinks as either a map (section -> pattern) or a list of maps with target/pattern keys.
  2. Check that your config provider/unmarshaller yields map[string]any or []map[string]any for the permalinks key.
  3. Validate the config with 'hugo config' to see the resolved permalinks value.

Example fix

# before (invalid)
permalinks = "/:year/:slug/"
# after
[permalinks]
posts = "/:year/:slug/"
Defensive patterns

Strategy: validation

Validate before calling

switch in.(type) {
case map[string]any, hmaps.Params:
    // map format
instance:
    if _, err := hmaps.ToSliceStringMap(in); err != nil {
        return fmt.Errorf("permalinks must be a map or list of maps")
    }
}

Type guard

func isPermalinksConfigShape(in any) bool {
    switch in.(type) {
    case map[string]any, hmaps.Params:
        return true
    }
    _, err := hmaps.ToSliceStringMap(in)
    return err == nil
}

Try / catch

cfg, err := page.DecodePermalinksConfig(raw)
if err != nil { /* fix config root shape */ }

Prevention

When it happens

Trigger: The [permalinks] config section resolves to an unexpected type, e.g. a bare string, a number, or a list of scalars rather than a map or list of maps. Usually a config-loading or unmarshalling issue.

Common situations: Mistyping the permalinks config (e.g. 'permalinks = "/:slug/"' instead of a map), config migration errors, or a custom config provider returning the wrong Go type.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/2498828ca3102218. Report an issue: GitHub.

Appendix: source

Thrown at resources/page/permalinks.go:531

// DecodePermalinksConfig decodes the permalinks configuration.
// It supports both the new slice-based format and the legacy map-based formats.
func DecodePermalinksConfig(in any) (PermalinksConfig, error) {
	if in == nil {
		return nil, nil
	}

	switch v := in.(type) {
	// Check legacy formats first.
	case map[string]any:
		return decodePermalinksMap(v)
	case hmaps.Params:
		return decodePermalinksMap(v)
	default:
		if ms, err := hmaps.ToSliceStringMap(in); err == nil {
			// New slice format.
			return decodePermalinksSlice(ms)
		}
		return nil, fmt.Errorf("permalinks: unsupported config type %T", in)
	}
}

func decodePermalinksSlice(ms []map[string]any) (PermalinksConfig, error) {
	var configs PermalinksConfig
	for _, m := range ms {
		m = hmaps.CleanConfigStringMap(m)
		var cfg PermalinkConfig

		if targetVal, ok := m["target"]; ok {
			if err := mapstructure.WeakDecode(targetVal, &cfg.Target); err != nil {
				return nil, fmt.Errorf("permalinks: failed to decode target: %w", err)
			}
			cfg.Target.Kind = strings.ToLower(cfg.Target.Kind)
			cfg.Target.Path = filepath.ToSlash(strings.ToLower(cfg.Target.Path))
		}

		if patternVal, ok := m["pattern"]; ok {

View on GitHub (pinned to 52c9bd7908)