gohugoio/hugo · error
can't iterate over %T
Error message
can't iterate over %T
What it means
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.
Source
Thrown at tpl/collections/where.go:55
if err != nil {
return nil, err
}
ctxv := reflect.ValueOf(ctx)
var path []string
kv := reflect.ValueOf(key)
if kv.Kind() == reflect.String {
path = strings.Split(strings.Trim(kv.String(), "."), ".")
}
switch seqv.Kind() {
case reflect.Array, reflect.Slice:
return ns.checkWhereArray(ctxv, seqv, kv, mv, path, op)
case reflect.Map:
return ns.checkWhereMap(ctxv, seqv, kv, mv, path, op)
default:
return nil, fmt.Errorf("can't iterate over %T", c)
}
}
func (ns *Namespace) checkCondition(v, mv reflect.Value, op string) (bool, error) {
v, vIsNil := hreflect.Indirect(v)
if !v.IsValid() {
vIsNil = true
}
mv, mvIsNil := hreflect.Indirect(mv)
if !mv.IsValid() {
mvIsNil = true
}
if vIsNil || mvIsNil {
switch op {
case "", "=", "==", "eq":
return vIsNil == mvIsNil, nil
case "!=", "<>", "ne":View on GitHub (pinned to 52c9bd7908)
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.
Example fix
// before
{{ where .Page "Section" "=" "posts" }}
// after
{{ where (slice .Page) "Section" "=" "posts" }} Defensive patterns
Strategy: type-guard
Validate before calling
func whereCollectionValid(c any) error {
k := reflect.ValueOf(c).Kind()
if k != reflect.Slice && k != reflect.Array && k != reflect.Map {
return fmt.Errorf("where needs slice/array/map, got %T", c)
}
return nil
} Type guard
func isWhereable(v any) bool {
if v == nil { return false }
k := reflect.ValueOf(v).Kind()
return k == reflect.Slice || k == reflect.Array || k == reflect.Map
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- operator argument must be string type
- isset unable to use key of type %T as index
- type %T not supported
- arguments to complement must be slices or arrays
- cannot index slice/array with type %s
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/5f4ebbec44dcd31a.
Report an issue: GitHub.