gohugoio/hugo · critical

permalinks configuration invalid: unknown value

Error message

permalinks configuration invalid: unknown value %q for key %q for kind %q

What it means

Hugo throws this when decoding a `[permalinks.<kind>]` config table where a sub-key's value is not a string. The decoder in `decodePermalinksMap` only accepts string patterns for each section glob inside a kind table; any other type (number, list, nested map) is rejected before a `PermalinkConfig` is built. It is a hard config-load failure, not a warning.

Solutions

  1. Change every value inside `[permalinks.<kind>]` tables to be a single quoted string pattern, e.g. `posts = "/posts/:slug/"`.
  2. Validate your `hugo.toml`/`config.yaml` permalinks block against the schema: each kind table maps section-glob to string.
  3. Run `hugo config` to dump the parsed permalinks and confirm types render as strings.
  4. Remove any nested maps or arrays under kind tables; move compound rules to separate section keys.

Example fix

// hugo.toml -- before
[permalinks.page]
posts = 123

// after
[permalinks.page]
posts = "/posts/:slug/"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: load hugo.toml and check every [permalinks.<kind>] value is a string.
import (
	"fmt"
	"github.com/spf13/viper"
)
func validatePermalinksKind(cfg *viper.Viper) error {
	for _, kind := range cfg.GetStringMap("permalinks") {
		m, ok := kind.(map[string]any)
		if !ok { continue }
		for _, v := range m {
			if _, ok := v.(string); !ok {
				return fmt.Errorf("permalinks kind value must be string, got %T", v)
			}
		}
	}
	return nil
}

Prevention

When it happens

Trigger: Calling config load / `hugo` build with a `permalinks` table like `[permalinks.page]` where an entry value is non-string, e.g. `posts = 123`, `posts = ["a","b"]`, or `posts = { pattern = "/x/" }`. Reached via the `hmaps.Params` branch of the type switch at permalinks.go:585-594.

Common situations: YAML/TOML indentation slip making a value a table instead of a string; copy-pasting a numeric weight into the pattern slot; mixing the old flat `permalinks.key = 'pattern'` form with the new `[permalinks.kind]` form incorrectly; upgrading from an older Hugo that tolerated looser typing.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/edadcc5ad3f7dc98. Report an issue: GitHub.

Appendix: 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 52c9bd7908)