gohugoio/hugo · error
permalinks: failed to decode target
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.).
Solutions
- Make 'target' a map with string-valued fields (kind, path, language, environment, sites).
- Move a path-only target string into target = { path = "/posts/**" }.
- 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
- Write 'target' as a map with string-valued fields.
- Put path-only targets in target = { path = "..." }.
- Check the wrapped error for the failing field.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- permalinks: pattern must be a string, got %T
- permalinks: unsupported config type %T
- failed to compile permalink target
- failed to decode page map
- permalink attribute not recognised
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/3310160661622736.
Report an issue: GitHub.
Appendix: 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, nilView on GitHub (pinned to 52c9bd7908)