gohugoio/hugo · error

can't iterate over a nil value

Error message

can't iterate over a nil value

What it means

After the literal-nil check, collections.Sort dereferences the value with hreflect.Indirect; if the argument is a typed nil (e.g. a nil pointer, nil map, or nil slice behind an interface), Indirect reports isNil and this error is returned. It distinguishes 'you passed nothing' (error 172) from 'you passed a typed value that is nil under the hood'.

Source

Thrown at tpl/collections/sort.go:38

	"sort"
	"strings"

	"github.com/gohugoio/hugo/common/hmaps"
	"github.com/gohugoio/hugo/common/hreflect"
	"github.com/gohugoio/hugo/langs"
	"github.com/gohugoio/hugo/tpl/compare"
	"github.com/spf13/cast"
)

// Sort returns a sorted copy of the list l.
func (ns *Namespace) Sort(ctx context.Context, l any, args ...any) (any, error) {
	if l == nil {
		return nil, errors.New("sequence must be provided")
	}

	seqv, isNil := hreflect.Indirect(reflect.ValueOf(l))
	if isNil {
		return nil, errors.New("can't iterate over a nil value")
	}

	ctxv := reflect.ValueOf(ctx)

	var sliceType reflect.Type
	switch seqv.Kind() {
	case reflect.Array, reflect.Slice:
		sliceType = seqv.Type()
	case reflect.Map:
		sliceType = reflect.SliceOf(seqv.Type().Elem())
	default:
		return nil, errors.New("can't sort " + reflect.ValueOf(l).Type().String())
	}

	collator := langs.GetCollator1(ns.deps.Conf.Language().(*langs.Language))

	// Create a list of pairs that will be used to do the sort
	p := pairList{Collator: collator, sortComp: ns.sortComp, SortAsc: true, SliceType: sliceType}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Wrap in `with` so nil values are skipped: `{{ with $seq }}{{ sort . }}{{ end }}`.
  2. Check the producing call — e.g. verify `.Site.GetPage "..."` actually finds a page before sorting anything derived from it.
  3. Initialize the collection (e.g. `slice` or `dict`) before conditionally appending, so it is never a typed nil.

Example fix

<!-- before -->
{{ $p := .Site.GetPage "/missing" }}
{{ sort $p.Pages }}
<!-- after -->
{{ with .Site.GetPage "/missing" }}{{ sort .Pages }}{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

{{ $items := site.Data.products }}
{{ with $items }}{{ range sort . "name" }}...{{ end }}{{ end }}

Type guard

{{ if ne $items nil }}{{ sort $items }}{{ end }}

Try / catch

{{ with try (sort site.Data.maybe) }}{{ if .Err }}{{ warnf "nothing to sort: %s" .Err }}{{ end }}{{ end }}

Prevention

When it happens

Trigger: Passing a nil pointer or nil-valued typed variable to `sort` — e.g. `{{ sort $p }}` where `$p` is a nil `*Page` or a nil map returned from a partial/function, or sorting a dereferenced pointer field that was never initialized.

Common situations: Sorting the result of `.GetPage` when the page doesn't exist (returns nil pointer); sorting data from `getJSON`/`resources` calls that failed and returned typed nil; passing scratch/store values that were set to a typed nil earlier in the template.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/22dd48111ac3f851.json. Report an issue: GitHub ↗.