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

  1. Pass an array or slice to apply — e.g. use `. .Pages` or `.Params.tags` rather than the parent map/object.
  2. Guard with `if reflect.IsSlice` / `len` checks before calling apply, or use `slice` / `delimit` helpers.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/af269126e0ab122b. Report an issue: GitHub.