gohugoio/hugo · error
can't apply over %v
Error message
can't apply over %v
What it means
Returned by the collections.Apply template function when the input collection c is not nil but its reflected Kind is neither Array nor Slice. Apply iterates the collection applying fname to each element; non-iterable kinds (map, struct, number, etc.) hit the default branch.
Source
Thrown at tpl/collections/apply.go:63
}
switch seqv.Kind() {
case reflect.Array, reflect.Slice:
r := make([]any, seqv.Len())
for i := range seqv.Len() {
vv := seqv.Index(i)
vvv, err := applyFnToThis(ctx, fnv, vv, args...)
if err != nil {
return nil, err
}
r[i] = vvv.Interface()
}
return r, nil
default:
return nil, fmt.Errorf("can't apply over %v", c)
}
}
var typeOfReflectValue = reflect.TypeFor[reflect.Value]()
func applyFnToThis(ctx context.Context, fn, this reflect.Value, args ...any) (reflect.Value, error) {
num := fn.Type().NumIn()
if num > 0 && hreflect.IsContextType(fn.Type().In(0)) {
args = append([]any{ctx}, args...)
}
n := make([]reflect.Value, len(args))
for i, arg := range args {
if arg == "." {
n[i] = this
} else {
n[i] = reflect.ValueOf(arg)
}View on GitHub (pinned to 52c9bd7908)
Solutions
- Pass an array or slice to apply — e.g. use `. .Pages` or `.Params.tags` rather than the parent map/object.
- Guard with `if reflect.IsSlice` / `len` checks before calling apply, or use `slice` / `delimit` helpers.
- For maps, extract a slice of values first (e.g. via a custom partial) before applying.
Example fix
// before
{{ $titles := apply .Params "partial getTitle" }}
// after
{{ $titles := apply .Params.tags "partial getTitle" }} Defensive patterns
Strategy: type-guard
Validate before calling
// Guard that the value is a slice/array before calling apply.
func isSliceOrArray(v any) bool {
switch reflect.ValueOf(v).Kind() {
case reflect.Slice, reflect.Array: return true
}
return false
} Type guard
// Go type guard narrowing to slice/array.
func asSlice(v any) ([]any, bool) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array { return nil, false }
out := make([]any, rv.Len())
for i := range rv.Len() { out[i] = rv.Index(i).Interface() }
return out, true
} Prevention
- Always pass an actual list (e.g. .Pages, .Params.tags) to apply.
- Guard template calls with `{{ if reflect.IsSlice .X }}`.
- Distinguish nil (returns empty slice) from wrong-type inputs.
When it happens
Trigger: Calling `apply collection "function" args...` in a template where collection is a map, scalar, struct, or channel — anything whose reflect.Kind is not Array/Slice. Nil is handled earlier (returns empty slice).
Common situations: Passing .Params (a map) instead of .Params.tags (a slice) to apply; passing a Page object instead of .Pages; a variable that resolved to a scalar after a failed lookup.
Related errors
- argument must be a slice
- can't iterate over %T
- union does not support slices or arrays of uncomparable type
- elements must be comparable
- expected a slice, got %T
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/af269126e0ab122b.
Report an issue: GitHub.