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

  1. Set each section key under the kind to a plain pattern string: `posts = '/:year/:slug/'`.
  2. For per-subsection rules use path globs in the section key (e.g. `"posts/tutorials" = ...`) or switch to the slice format with `target.path`.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/edadcc5ad3f7dc98.json. Report an issue: GitHub ↗.