gohugoio/hugo · error

can't evaluate an invalid value

Error message

can't evaluate an invalid value

What it means

The `where` and `sort` functions walk a dotted key path (e.g. `.Author.Name`) by calling `evaluateSubElem` for each segment. If an intermediate reflect.Value is not valid (`!obj.IsValid()`), the field/method/map navigation cannot proceed and this error fires. An invalid Value typically results from a missing map key or an absent struct field on a prior path segment.

Solutions

  1. Ensure all elements share the same structure for the given key path.
  2. Use a single-level key or flatten the data so the path always resolves.
  3. Filter the collection first to items that have the nested field, then apply `where`.

Example fix

// before
{{ where .Pages "Author.Name" "eq" "Alice" }}
// after
{{ $withAuthor := where .Pages "Author" "ne" nil }}
{{ where $withAuthor "Author.Name" "eq" "Alice" }}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-filter elements that have the nested key before applying a dotted path
{{ $hasKey := where .Pages "Author" "ne" nil }}
{{ where $hasKey "Author.Name" "eq" "Alice" }}

Type guard

func pathResolvesOnAll(elemType reflect.Type, path []string) bool {
    t := elemType
    if t.Kind() == reflect.Pointer { t = t.Elem() }
    for _, seg := range path {
        switch t.Kind() {
        case reflect.Struct:
            f, ok := t.FieldByName(seg)
            if !ok { return false }
            t = f.Type
        case reflect.Map:
            t = t.Elem()
        default:
            return false
        }
        if t.Kind() == reflect.Pointer { t = t.Elem() }
    }
    return true
}

Prevention

When it happens

Trigger: Calling `{{ where .Pages "Author.Name" "eq" "Alice" }}` where some pages have no `Author` map (so `.Author` yields an invalid zero Value), or using a dotted path where a middle segment does not exist on the element type.

Common situations: Heterogeneous collections where some items have a nested field and others do not. The developer expects missing keys to be skipped but the evaluation short-circuits on the invalid intermediate value.

Related errors


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

Appendix: source

Thrown at tpl/collections/where.go:314

		if svp != nil && smvp != nil {
			re, err := hstrings.GetOrCompileRegexp(*smvp)
			if err != nil {
				return false, err
			}
			if re.MatchString(*svp) {
				return true, nil
			}
			return false, nil
		}
	default:
		return false, errors.New("no such operator")
	}
	return false, nil
}

func evaluateSubElem(ctx, obj reflect.Value, elemName string) (reflect.Value, error) {
	if !obj.IsValid() {
		return zero, errors.New("can't evaluate an invalid value")
	}

	typ := obj.Type()
	obj, isNil := hreflect.Indirect(obj)

	// first, check whether obj has a method. In this case, obj is
	// a struct or its pointer. If obj is a struct,
	// to check all T and *T method, use obj pointer type Value
	objPtr := obj
	if !hreflect.IsInterfaceOrPointer(objPtr.Kind()) && objPtr.CanAddr() {
		objPtr = objPtr.Addr()
	}

	mt := hreflect.GetMethodByNameForType(objPtr.Type(), elemName)
	if mt.Func.IsValid() {
		// Receiver is the first argument.
		args := []reflect.Value{objPtr}
		num := mt.Type.NumIn()

View on GitHub (pinned to 52c9bd7908)