gohugoio/hugo · error

errPermalinkAttributeUnknown

errPermalinkAttributeUnknown

Error message

permalink attribute not recognised

What it means

Hugo compiles each permalink pattern by matching `:attribute` tokens (regexp `:\w+(\[.+?\])?`) against its table of known permalink attributes (:year, :month, :day, :slug, :title, :section, :sections, :filename, :slugorfilename, plus date-format and taxonomy variants). A token that isn't in that table — and isn't a page front-matter field usable as an attribute — produces errPermalinkAttributeUnknown, wrapped with the offending pattern, and the config fails to load.

Source

Thrown at resources/page/permalinks.go:272

	})
}

// pageToPermaAttribute is the type of a function which, given a page and a tag
// can return a string to go in that position in the page (or an error)
type pageToPermaAttribute func(Page, string) (string, error)

var attributeRegexp = regexp.MustCompile(`:\w+(\[.+?\])?`)

type permalinkExpandError struct {
	pattern string
	err     error
}

func (pee *permalinkExpandError) Error() string {
	return fmt.Sprintf("error expanding %q: %s", pee.pattern, pee.err)
}

var errPermalinkAttributeUnknown = errors.New("permalink attribute not recognised")

func (l PermalinkExpander) pageToPermalinkDate(p Page, dateField string) (string, error) {
	// a Page contains a Node which provides a field Date, time.Time
	switch dateField {
	case "year":
		return strconv.Itoa(p.Date().Year()), nil
	case "month":
		return fmt.Sprintf("%02d", int(p.Date().Month())), nil
	case "monthname":
		return p.Date().Month().String(), nil
	case "day":
		return fmt.Sprintf("%02d", p.Date().Day()), nil
	case "weekday":
		return strconv.Itoa(int(p.Date().Weekday())), nil
	case "weekdayname":
		return p.Date().Weekday().String(), nil
	case "yearday":
		return strconv.Itoa(p.Date().YearDay()), nil

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Check the pattern quoted in the error and compare each `:token` against Hugo's documented permalink tokens (gohugo.io/content-management/urls/#tokens); fix the spelling.
  2. For custom values, use a front-matter field whose name matches the token, or set `url` in front matter instead.
  3. For section slices use the documented syntax, e.g. `/:sections[last]/` or `/:sections[1:]/`.

Example fix

# before
[permalinks]
  posts = '/:yearmonth/:slug/'
# after
[permalinks]
  posts = '/:year/:month/:slug/'
Defensive patterns

Strategy: validation

Validate before calling

var knownAttrs = map[string]bool{"year": true, "month": true, "monthname": true, "day": true, "weekday": true, "weekdayname": true, "yearday": true, "section": true, "sections": true, "title": true, "slug": true, "slugorfilename": true, "filename": true, "contentbasename": true}
for _, m := range regexp.MustCompile(`:(\w+)`).FindAllStringSubmatch(pattern, -1) {
    if !knownAttrs[strings.ToLower(m[1])] {
        return fmt.Errorf("unknown permalink attribute :%s in %q", m[1], pattern)
    }
}

Prevention

When it happens

Trigger: A `permalinks` entry containing an unrecognized `:token`, e.g. `posts = "/:categories/:slug/"` when no matching attribute or front-matter field resolves, or misspellings like `:filename` vs `:file`, `:sections[1]` syntax errors.

Common situations: Typos (`:tittle`, `:yearmonth`); using another SSG's tokens (Jekyll's `:categories` semantics); expecting a custom front-matter field to work when the field name collides with nothing known; wrong `:sections[...]` range syntax.

Related errors


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