gohugoio/hugo · error

failed to compile permalink target %d: %w

Error message

failed to compile permalink target %d: %w

What it means

PermalinksConfig.InitConfig runs at config load and compiles the sites-matrix matcher (target selector) for each configured permalink rule. If a rule's Target cannot be compiled against the configured dimensions (languages/roles/versions), config initialization fails with this error, wrapping the underlying compile error and reporting the zero-based rule index.

Source

Thrown at resources/page/permalinks.go:50

	"github.com/gohugoio/hugo/resources/kinds"
	"github.com/mitchellh/mapstructure"
)

// PermalinkConfig holds a single permalink rule with a target matcher and a pattern.
type PermalinkConfig struct {
	Target  PageMatcher
	Pattern string
}

// PermalinksConfig is an ordered slice of permalink rules.
// For any given Page, the first matching rule wins.
type PermalinksConfig []PermalinkConfig

// InitConfig compiles the sites matrix for each permalink target.
func (c PermalinksConfig) InitConfig(logger loggers.Logger, defaultSitesMatrix sitesmatrix.VectorStore, configuredDimensions *sitesmatrix.ConfiguredDimensions) error {
	for i := range c {
		if err := c[i].Target.compileSitesMatrix(nil, configuredDimensions); err != nil {
			return fmt.Errorf("failed to compile permalink target %d: %w", i, err)
		}
	}
	return nil
}

// PermalinkExpander holds permalink mappings.
type PermalinkExpander struct {
	// knownPermalinkAttributes maps :tags in a permalink specification to a
	// function which, given a page and the tag, returns the resulting string
	// to be used to replace that tag.
	knownPermalinkAttributes map[string]pageToPermaAttribute

	configs PermalinksConfig

	urlize func(uri string) string

	patternCache *hmaps.Cache[string, func(Page) (string, error)]
}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Look at rule index N (zero-based) in your `permalinks` config and fix the target matcher named in the wrapped error.
  2. Ensure every dimension value referenced (language, etc.) exists in the site configuration exactly as spelled.
  3. Simplify to the plain `permalinks: { posts: "/:year/:slug/" }` form if you don't need per-target matching.

Example fix

# before (hugo.toml) — 'nn' not a configured language
[[permalinks.config]]
  [permalinks.config.target]
    lang = 'nn'
  pattern = '/:slug/'
# after
  [permalinks.config.target]
    lang = 'nb'
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check permalink patterns from config before site build
for kind, pattern := range permalinksConfig {
    if !strings.HasPrefix(pattern, "/") {
        return fmt.Errorf("permalink for %q must start with '/': %q", kind, pattern)
    }
    if strings.Contains(pattern, "::") || strings.HasSuffix(pattern, ":") {
        return fmt.Errorf("malformed attribute in permalink %q", pattern)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to compile permalink") {
    // bad pattern in [permalinks] config — fix the pattern, don't ignore
}

Prevention

When it happens

Trigger: Starting a build with a `permalinks` config using the structured target form where the target matcher references invalid values — e.g. a language, role, or version dimension value not present in the site's configured dimensions, or a malformed matcher expression.

Common situations: Multilingual configs where a permalink rule targets a language code that was removed or renamed; typos in dimension values; upgrading to a Hugo version with the sites-matrix model and carrying over stale target definitions.

Related errors


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