{"id":"f76b0e41521862a8","repo":"gohugoio/hugo","slug":"nil-is-not-a-valid-key-to-group-by","errorCode":null,"errorMessage":"nil is not a valid key to group by","messagePattern":"nil is not a valid key to group by","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/collections.go","lineNumber":314,"sourceCode":"\t\t\t\t\t}\n\n\t\t\t\t\tins.handleValuePair(l1vv, l2vv)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ins.r.Interface(), nil\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"can't iterate over \" + reflect.ValueOf(l2).Type().String())\n\t\t}\n\tdefault:\n\t\treturn nil, errors.New(\"can't iterate over \" + reflect.ValueOf(l1).Type().String())\n\t}\n}\n\n// Group groups a set of items by the given key.\n// This is currently only supported for Pages.\nfunc (ns *Namespace) Group(key any, items any) (any, error) {\n\tif key == nil {\n\t\treturn nil, errors.New(\"nil is not a valid key to group by\")\n\t}\n\n\tif g, ok := items.(collections.Grouper); ok {\n\t\treturn g.Group(key, items)\n\t}\n\n\tin := newSliceElement(items)\n\n\tif g, ok := in.(collections.Grouper); ok {\n\t\treturn g.Group(key, items)\n\t}\n\n\treturn nil, fmt.Errorf(\"grouping not supported for type %T %T\", items, in)\n}\n\n// IsSet returns whether a given array, channel, slice, or map in c has the given key\n// defined.\nfunc (ns *Namespace) IsSet(c any, key any) (bool, error) {","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/collections.go#L296-L332","documentation":"`group` requires a non-nil key (the group label) as its first argument; Hugo checks this before delegating to the Pages `Grouper` implementation. A nil key would produce a group with no usable name, so it's rejected up front.","triggerScenarios":"`{{ group nil $pages }}` or `{{ group .Params.section $pages }}` where the param is unset, e.g. building grouped lists with a key read from front matter or a loop variable that can be nil.","commonSituations":"Grouping pages by a front-matter field that some pages omit, passing an unset scratch/variable as the key, or reversing the argument order so the pages land in the key slot as nil after a bad lookup.","solutions":["Default the key to a string: `{{ $g := group (.Params.category | default \"uncategorized\") $pages }}`.","Verify argument order — key first, pages second: `{{ group \"recent\" $pages }}`.","Filter out or pre-bucket items whose grouping field is missing before calling group."],"exampleFix":"<!-- before -->\n{{ $g := group .Params.series .Pages }}\n<!-- after -->\n{{ $g := group (.Params.series | default \"other\") .Pages }}","handlingStrategy":"validation","validationCode":"{{ $key := .Params.groupKey | default \"Section\" }}\n{{ if $key }}{{ $groups := .Pages.GroupByParam $key }}{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass nil as the group key — apply `| default` to any dynamic key before GroupBy/GroupByParam","Validate front-matter-driven grouping keys exist with `isset` before use","Fail fast in partials with `errorf \"missing group key\"` rather than forwarding nil"],"tags":["hugo","templates","collections","group","nil"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}