gohugoio/hugo · error
permalinks configuration invalid: unknown value %q for key %
Error message
permalinks configuration invalid: unknown value %q for key %q for kind %q
What it means
Within a kind-scoped permalinks table like `[permalinks.page]`, every value must be a pattern string keyed by section glob. When a nested value is anything other than a string (e.g. another table, number, or list), decodePermalinksMap fails with this error, naming the offending value, key, and kind. Deeper nesting than two levels is not supported.
Source
Thrown at resources/page/permalinks.go:592
configs = append(configs,
PermalinkConfig{Target: PageMatcher{Kind: kinds.KindPage, Path: sectionToPathGlob(k)}, Pattern: v},
PermalinkConfig{Target: PageMatcher{Kind: kinds.KindTerm, Path: sectionToPathGlob(k)}, Pattern: v},
)
case hmaps.Params:
// [permalinks.kind]
// section = '...'
if !hstrings.InSlice(permalinksKindsSupport, k) {
return nil, fmt.Errorf("permalinks configuration not supported for kind %q, supported kinds are %v", k, permalinksKindsSupport)
}
for k2, v2 := range v {
switch v2 := v2.(type) {
case string:
configs = append(configs,
PermalinkConfig{Target: PageMatcher{Kind: k, Path: sectionToPathGlob(k2)}, Pattern: v2},
)
default:
return nil, fmt.Errorf("permalinks configuration invalid: unknown value %q for key %q for kind %q", v2, k2, k)
}
}
default:
return nil, fmt.Errorf("permalinks configuration invalid: unknown value %q for key %q", v, k)
}
}
return configs, nil
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Set each section key under the kind to a plain pattern string: `posts = '/:year/:slug/'`.
- For per-subsection rules use path globs in the section key (e.g. `"posts/tutorials" = ...`) or switch to the slice format with `target.path`.
- Quote YAML values so they parse as strings.
Example fix
# before [permalinks.page.posts] pattern = "/:year/:slug/" # after [permalinks.page] posts = "/:year/:slug/"
Defensive patterns
Strategy: validation
Validate before calling
// use only documented tokens: :year :month :day :slug :title :section :sections :filename :slugorfilename :contentbasename ...
re := regexp.MustCompile(`:[a-zA-Z]+`)
known := map[string]bool{":year": true, ":month": true, ":day": true, ":slug": true, ":title": true, ":section": true, ":sections": true, ":filename": true, ":slugorfilename": true}
for _, tok := range re.FindAllString(pattern, -1) {
if !known[tok] { /* invalid token */ }
} Prevention
- Check the Hugo permalink token docs before using a :token — some tokens are only valid for certain kinds (e.g. date tokens need page dates)
- Watch for typos like :slugs or :years
- Test with `hugo --renderToMemory` in CI to catch config errors early
When it happens
Trigger: `[permalinks.page.posts]` with further nested keys (making `posts` a map instead of a string), or `posts = 123` / `posts = ["a"]` under `[permalinks.page]`.
Common situations: Trying to nest per-subsection rules a level too deep; YAML indentation that turns a string into a mapping; unquoted values parsing as non-strings.
Related errors
- permalinks: pattern must be a string, got %T
- failed to compile permalink target %d: %w
- errPermalinkAttributeUnknown
- permalinks: unsupported config type %T
- permalinks: missing pattern
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/edadcc5ad3f7dc98.json.
Report an issue: GitHub ↗.