{"record":{"id":"5f4ebbec44dcd31a","repo":"gohugoio/hugo","slug":"can-t-iterate-over-t-5f4ebb","errorCode":null,"errorMessage":"can't iterate over %T","messagePattern":"can't iterate over %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/where.go","lineNumber":55,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tctxv := reflect.ValueOf(ctx)\n\n\tvar path []string\n\tkv := reflect.ValueOf(key)\n\tif kv.Kind() == reflect.String {\n\t\tpath = strings.Split(strings.Trim(kv.String(), \".\"), \".\")\n\t}\n\n\tswitch seqv.Kind() {\n\tcase reflect.Array, reflect.Slice:\n\t\treturn ns.checkWhereArray(ctxv, seqv, kv, mv, path, op)\n\tcase reflect.Map:\n\t\treturn ns.checkWhereMap(ctxv, seqv, kv, mv, path, op)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"can't iterate over %T\", c)\n\t}\n}\n\nfunc (ns *Namespace) checkCondition(v, mv reflect.Value, op string) (bool, error) {\n\tv, vIsNil := hreflect.Indirect(v)\n\tif !v.IsValid() {\n\t\tvIsNil = true\n\t}\n\n\tmv, mvIsNil := hreflect.Indirect(mv)\n\tif !mv.IsValid() {\n\t\tmvIsNil = true\n\t}\n\tif vIsNil || mvIsNil {\n\t\tswitch op {\n\t\tcase \"\", \"=\", \"==\", \"eq\":\n\t\t\treturn vIsNil == mvIsNil, nil\n\t\tcase \"!=\", \"<>\", \"ne\":","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/where.go#L37-L73","documentation":"Thrown by Namespace.Where when the collection `c` is reflect-kind neither Array, Slice, nor Map. Where filters a collection by a key/field and operator; it supports slices/arrays (element-wise field match) and maps (value-wise). Any other kind (struct, string, int, func, chan) is rejected with the collection's type named via %T.","triggerScenarios":"Calling `{{ where $singlePage \"Section\" \"=\" \"posts\" }}` (a struct, not a collection), `{{ where \"hello\" 0 \"=\" \"h\" }}`, or `{{ where 42 \"k\" \"=\" 1 }}`. The switch over seqv.Kind() handles only Slice/Array/Map; everything else hits the default branch.","commonSituations":"Author forgets to wrap a single page in a slice, passes a scalar variable that was expected to be a list, or chains where after an operation that collapsed a slice to a single value. Common with `.Page` vs `.Pages` mix-ups.","solutions":["Pass a slice/map of items: `{{ where .Pages \"Section\" \"=\" \"posts\" }}`.","Wrap a single item: `{{ where (slice .Page) \"Section\" \"=\" \"posts\" }}`.","Verify the variable is a collection before calling where.","Use a different filter (e.g. `if eq .Section \"posts\"`) for single values."],"exampleFix":"// before\n{{ where .Page \"Section\" \"=\" \"posts\" }}\n// after\n{{ where (slice .Page) \"Section\" \"=\" \"posts\" }}","handlingStrategy":"type-guard","validationCode":"func whereCollectionValid(c any) error {\n    k := reflect.ValueOf(c).Kind()\n    if k != reflect.Slice && k != reflect.Array && k != reflect.Map {\n        return fmt.Errorf(\"where needs slice/array/map, got %T\", c)\n    }\n    return nil\n}","typeGuard":"func isWhereable(v any) bool {\n    if v == nil { return false }\n    k := reflect.ValueOf(v).Kind()\n    return k == reflect.Slice || k == reflect.Array || k == reflect.Map\n}","tryCatchPattern":null,"preventionTips":["Pass a slice/array/map of items to where.","Wrap a single page in a slice: `where (slice .Page) ...`.","Use `if eq` for single-value filtering instead of where.","Verify the variable is a collection before calling where."],"tags":["go","hugo","template","collections","where","type-error"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}