gohugoio/hugo · error
key %q not allowed in cascade config
Error message
key %q not allowed in cascade config
What it means
Cascade entries are decoded in resources/page/page_matcher.go, and any key present in `disallowedCascadeKeys` — `kind`, `path`, `lang`, and `cascade` — is rejected at the top level of a cascade block. These four keys define the structure of the page tree (or would recurse), so Hugo cannot let a cascade rewrite them on descendant pages. Note they *are* valid inside a cascade's `_target` matcher; only the value side is forbidden.
Source
Thrown at resources/page/page_matcher.go:161
if err != nil {
return CascadeConfig{}, nil, err
}
var cfgs []PageMatcherParamsConfig
for _, m := range ms {
m = hmaps.CleanConfigStringMap(m)
var (
c PageMatcherParamsConfig
err error
)
c, err = dec.mapToPageMatcherParamsConfig(m)
if err != nil {
return CascadeConfig{}, nil, err
}
for k := range m {
if disallowedCascadeKeys[k] {
return CascadeConfig{}, nil, fmt.Errorf("key %q not allowed in cascade config", k)
}
}
cfgs = append(cfgs, c)
}
if len(cfgs) == 0 {
return CascadeConfig{}, nil, nil
}
var n int
for _, cfg := range cfgs {
if len(cfg.Params) > 0 || len(cfg.Fields) > 0 {
cfgs[n] = cfg
n++
}
}
if n == 0 {View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Move `kind`, `path`, and `lang` into the cascade's `_target` block — that's where they act as matchers.
- Delete any nested `cascade:` key; cascade already propagates down the tree, so nesting is unnecessary and disallowed.
- If you truly need to set a page's kind or language, do it on the page itself (front matter / filename language suffix), not via cascade.
- Run `hugo config` to see the decoded cascade and confirm the shape matches `_target` + params.
Example fix
# before
cascade:
kind: section
banner: hero.jpg
# after
cascade:
- _target:
kind: section
banner: hero.jpg Defensive patterns
Strategy: validation
Validate before calling
// only use allowed keys in a cascade _target/params block
allowed := map[string]bool{"path": true, "kind": true, "lang": true, "environment": true}
for k := range targetMap {
if !allowed[strings.ToLower(k)] {
return fmt.Errorf("cascade target key %q not allowed", k)
}
} Prevention
- In cascade `_target` blocks use only path, kind, lang, environment
- Don't nest arbitrary params inside _target — put them at the cascade level instead
- Review the Hugo cascade docs after upgrades; allowed keys are versioned
When it happens
Trigger: Writing `cascade:` in front matter or `[[cascade]]` in site config with `kind:`, `path:`, `lang:`, or a nested `cascade:` as a sibling of `_target`/params, instead of placing `kind`/`path`/`lang` inside `_target`.
Common situations: Confusing the matcher and the payload: intending to restrict a cascade to `kind: section` but putting `kind` at the cascade level rather than under `_target`; attempting nested cascades to build multi-level inheritance; copying a `_target` block from docs and dropping the `_target` wrapper.
Related errors
- %q did not match a valid Page Kind
- media type %q not found
- failed to compile cascade target %d: %w
- failed to decode build config in front matter: %s%s
- failed to decode sitemap config in front matter: %s
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/9b12ab4952788a09.json.
Report an issue: GitHub ↗.