gohugoio/hugo · error
permalinks: pattern must be a string, got %T
Error message
permalinks: pattern must be a string, got %T
What it means
In the new slice-based permalinks format, each entry's `pattern` key must hold a string. decodePermalinksSlice does a direct type assertion `patternVal.(string)` and errors with the actual Go type if the value is anything else. This is a strict check — no coercion of numbers, booleans, or nested maps is attempted.
Source
Thrown at resources/page/permalinks.go:552
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
}
func decodePermalinksMap(m map[string]any) (PermalinksConfig, error) {
var configs PermalinksConfig
config := hmaps.CleanConfigStringMap(m)
for k, v := range config {
switch v := v.(type) {
case string:View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Quote the pattern so it parses as a string: `pattern = "/:year/:slug/"`.
- Ensure each entry in the permalinks array has `pattern` as a plain string, with target options under `target` instead.
Example fix
# before [[permalinks]] pattern = 2024 # after [[permalinks]] pattern = "/2024/:slug/"
Defensive patterns
Strategy: type-guard
Validate before calling
// each permalink value must be a string: // [permalinks.page] // posts = "/:year/:month/:slug/"
Type guard
func isStringPattern(v any) bool { _, ok := v.(string); return ok } Prevention
- Always quote permalink patterns so YAML/TOML doesn't coerce them (e.g. bare `/:year/` may parse oddly)
- Avoid nesting deeper than kind→section→string
- Lint config in CI with `hugo config --format json | jq '.permalinks'`
When it happens
Trigger: An array-format permalinks entry where `pattern` is a non-string, e.g. `pattern = 2024`, `pattern = true`, an array, or an inline table; also YAML values that parse as numbers/dates instead of strings when unquoted.
Common situations: Unquoted YAML values that the parser types as int/bool/date; accidentally nesting a map under `pattern`; generating config from templates/scripts that emit typed values.
Related errors
- permalinks configuration invalid: unknown value %q for key %
- 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/1a62d30630e04a7e.json.
Report an issue: GitHub ↗.