{"id":"9b12ab4952788a09","repo":"gohugoio/hugo","slug":"key-q-not-allowed-in-cascade-config","errorCode":null,"errorMessage":"key %q not allowed in cascade config","messagePattern":"key %q not allowed in cascade config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/page/page_matcher.go","lineNumber":161,"sourceCode":"\t\tif err != nil {\n\t\t\treturn CascadeConfig{}, nil, err\n\t\t}\n\n\t\tvar cfgs []PageMatcherParamsConfig\n\n\t\tfor _, m := range ms {\n\t\t\tm = hmaps.CleanConfigStringMap(m)\n\t\t\tvar (\n\t\t\t\tc   PageMatcherParamsConfig\n\t\t\t\terr error\n\t\t\t)\n\t\t\tc, err = dec.mapToPageMatcherParamsConfig(m)\n\t\t\tif err != nil {\n\t\t\t\treturn CascadeConfig{}, nil, err\n\t\t\t}\n\t\t\tfor k := range m {\n\t\t\t\tif disallowedCascadeKeys[k] {\n\t\t\t\t\treturn CascadeConfig{}, nil, fmt.Errorf(\"key %q not allowed in cascade config\", k)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcfgs = append(cfgs, c)\n\t\t}\n\n\t\tif len(cfgs) == 0 {\n\t\t\treturn CascadeConfig{}, nil, nil\n\t\t}\n\n\t\tvar n int\n\t\tfor _, cfg := range cfgs {\n\t\t\tif len(cfg.Params) > 0 || len(cfg.Fields) > 0 {\n\t\t\t\tcfgs[n] = cfg\n\t\t\t\tn++\n\t\t\t}\n\t\t}\n\n\t\tif n == 0 {","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/resources/page/page_matcher.go#L143-L179","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":"# before\ncascade:\n  kind: section\n  banner: hero.jpg\n\n# after\ncascade:\n  - _target:\n      kind: section\n    banner: hero.jpg","handlingStrategy":"validation","validationCode":"// only use allowed keys in a cascade _target/params block\nallowed := map[string]bool{\"path\": true, \"kind\": true, \"lang\": true, \"environment\": true}\nfor k := range targetMap {\n    if !allowed[strings.ToLower(k)] {\n        return fmt.Errorf(\"cascade target key %q not allowed\", k)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["hugo","cascade","front-matter","config","page-matcher"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}