gohugoio/hugo · error

permalinks: failed to decode target: %w

Error message

permalinks: failed to decode target: %w

What it means

Thrown by decodePermalinksSlice when mapstructure.WeakDecode of a rule's 'target' value into the PageMatcher struct fails. The wrapped error is the decode failure, so the target object's fields do not fit the PageMatcher schema (kind, path, language, environment, sites, etc.).

Source

Thrown at resources/page/permalinks.go:543

		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 {
			cfg.Pattern, ok = patternVal.(string)
			if !ok {
				return nil, fmt.Errorf("permalinks: pattern must be a string, got %T", patternVal)
			}
		} else {
			return nil, fmt.Errorf("permalinks: missing pattern")
		}

		configs = append(configs, cfg)
	}

	return configs, nil

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Make 'target' a map with string-valued fields (kind, path, language, environment, sites).
  2. Move a path-only target string into target = { path = "/posts/**" }.
  3. Check the wrapped error for the specific field that failed to decode.

Example fix

# before
[[permalinks]]
target = "/posts/**"
pattern = "/:year/:slug/"
# after
[[permalinks]]
target = { path = "/posts/**" }
pattern = "/:year/:slug/"
Defensive patterns

Strategy: validation

Validate before calling

if tv, ok := m["target"]; ok {
    if err := mapstructure.WeakDecode(tv, &page.PageMatcher{}); err != nil {
        return fmt.Errorf("target shape invalid: %w", err)
    }
}

Try / catch

cfg, err := page.DecodePermalinksConfig(raw)
if err != nil { /* fix the offending target object */ }

Prevention

When it happens

Trigger: A list-format permalink rule whose 'target' has wrong field types, e.g. target = { kind = 123 } (int instead of string) or target = "/posts/**" (string instead of a map).

Common situations: Migrating from the map format to the new slice format and writing target as a plain string path, or typos in target field names/types.

Understand the failure class

Related errors


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