gohugoio/hugo · error

index of nil pointer

Error message

index of nil pointer

What it means

Returned by the index builtin when, after indirect dereferencing, the item is a nil pointer (isNil == true). Indexing through a nil pointer is invalid because the underlying value does not exist. This occurs when the collection is a typed nil pointer to a slice/map/array.

Source

Thrown at tpl/internal/go_templates/texttemplate/funcs.go:207

	}
	return int(x), nil
}

// Indexing.

// index returns the result of indexing its first argument by the following
// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
// indexed item must be a map, slice, or array.
func index(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) {
	item = indirectInterface(item)
	if !item.IsValid() {
		return reflect.Value{}, fmt.Errorf("index of untyped nil")
	}
	for _, index := range indexes {
		index = indirectInterface(index)
		var isNil bool
		if item, isNil = indirect(item); isNil {
			return reflect.Value{}, fmt.Errorf("index of nil pointer")
		}
		switch item.Kind() {
		case reflect.Array, reflect.Slice, reflect.String:
			x, err := indexArg(index, item.Len())
			if err != nil {
				return reflect.Value{}, err
			}
			item = item.Index(x)
		case reflect.Map:
			index, err := prepareArg(index, item.Type().Key())
			if err != nil {
				return reflect.Value{}, err
			}
			if x := item.MapIndex(index); x.IsValid() {
				item = x
			} else {
				item = reflect.Zero(item.Type().Elem())
			}

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Guard with {{if .Ptr}}{{index .Ptr 0}}{{end}} or use {{with .Ptr}}{{index . 0}}{{end}}.
  2. Initialize pointer-to-collection fields to non-nil in the data layer (allocate the slice/map).
  3. Prefer non-pointer collection fields in the data model when nil is not meaningful.
  4. Return a zero value via a helper func when the pointer is nil.

Example fix

// before
{{index .Items 0}} // .Items is *[]T and nil -> error

// after
{{with .Items}}{{index . 0}}{{end}}
// or allocate: data.Items = &[]T{} before render
Defensive patterns

Strategy: validation

Validate before calling

// avoid pointer-to-collection fields, or allocate them
type Data struct{ Items *[]any }
func init() { d.Items = &[]any{} } // never nil

Type guard

func isNonNilPointerToCollection(v any) bool {
    rv := reflect.ValueOf(v)
    if rv.Kind() != reflect.Pointer || rv.IsNil() { return false }
    switch rv.Type().Elem().Kind() {
    case reflect.Slice, reflect.Array, reflect.Map: return true
    }
    return false
}

Prevention

When it happens

Trigger: Calling {{index .Ptr 0}} where .Ptr is a *[]T or *map[K]V that is nil; a struct field typed as a pointer to a collection that was never allocated.

Common situations: Optional pointer-to-slice fields left nil in the data model; nested structs where a parent pointer is nil; JSON unmarshaling that leaves pointer fields nil for absent keys.

Related errors


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