gohugoio/hugo · error

is neither a struct field, a method nor a map element of…

Error message

%s is neither a struct field, a method nor a map element of type %s

What it means

The fallthrough case in `evaluateSubElem` (where.go:384): the name matched no method, the value is not nil, and the object's Kind is neither `Struct` nor `Map` (e.g. it is a basic scalar, slice, array, channel, or func). Hugo reports that the name is neither a struct field, a method, nor a map element of the given type.

Solutions

  1. Confirm the element type is actually a struct or map; if it's scalar, filter directly without a key (`{{ where $nums ">" 5 }}` is invalid — use `range` + `if`).
  2. Wrap scalars in structs with a `Value` field during data preparation.
  3. Verify the collection is not a nested slice-of-slices where the inner element is itself a slice.

Example fix

// before
{{ where $numbers "Value" ">" 5 }}  {{/* $numbers is []int */}}
// after
{{ range $n := $numbers }}{{ if gt $n 5 }}...{{ end }}{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

// Go-side: only pass collections whose element kind is Struct or Map
k := reflect.TypeOf(slice).Elem().Kind()
if k != reflect.Struct && k != reflect.Map {
    // wrap scalars or use a different filter strategy
}

Prevention

When it happens

Trigger: `{{ where $numbers "Foo" ... }}` where `$numbers` is a slice of `int`; querying a field on a collection whose elements are primitives.

Common situations: Filtering a slice of scalars as if it were a slice of objects; a generic `[]any` whose elements are not all structs/maps; misconfigured data shape.

Related errors


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

Appendix: source

Thrown at tpl/collections/where.go:384

	obj = reflect.Indirect(obj)
	switch obj.Kind() {
	case reflect.Struct:
		ft, ok := obj.Type().FieldByName(elemName)
		if ok {
			if ft.PkgPath != "" && !ft.Anonymous {
				return zero, fmt.Errorf("%s is an unexported field of struct type %s", elemName, typ)
			}
			return obj.FieldByIndex(ft.Index), nil
		}
		return zero, fmt.Errorf("%s isn't a field of struct type %s", elemName, typ)
	case reflect.Map:
		kv := reflect.ValueOf(elemName)
		if kv.Type().AssignableTo(obj.Type().Key()) {
			return obj.MapIndex(kv), nil
		}
		return zero, fmt.Errorf("%s isn't a key of map type %s", elemName, typ)
	}
	return zero, fmt.Errorf("%s is neither a struct field, a method nor a map element of type %s", elemName, typ)
}

// parseWhereArgs parses the end arguments to the where function.  Return a
// match value and an operator, if one is defined.
func parseWhereArgs(args ...any) (mv reflect.Value, op string, err error) {
	switch len(args) {
	case 1:
		mv = reflect.ValueOf(args[0])
	case 2:
		var ok bool
		if op, ok = args[0].(string); !ok {
			err = errors.New("operator argument must be string type")
			return
		}
		op = strings.TrimSpace(strings.ToLower(op))
		mv = reflect.ValueOf(args[1])
	default:
		err = errors.New("can't evaluate the array by no match argument or more than or equal to two arguments")

View on GitHub (pinned to 52c9bd7908)