gohugoio/hugo · error

isset unable to use key of type %T as index

Error message

isset unable to use key of type %T as index

What it means

Hugo's `isset` template function checks whether an index/key exists in a collection. When the collection is an array, slice, or channel, the key must be castable to an integer index; this error is returned when `cast.ToIntE` fails on the supplied key, e.g. a non-numeric string used against a slice.

Source

Thrown at tpl/collections/collections.go:340

	if g, ok := in.(collections.Grouper); ok {
		return g.Group(key, items)
	}

	return nil, fmt.Errorf("grouping not supported for type %T %T", items, in)
}

// IsSet returns whether a given array, channel, slice, or map in c has the given key
// defined.
func (ns *Namespace) IsSet(c any, key any) (bool, error) {
	av := reflect.ValueOf(c)
	kv := reflect.ValueOf(key)

	switch av.Kind() {
	case reflect.Array, reflect.Chan, reflect.Slice:
		k, err := cast.ToIntE(key)
		if err != nil {
			return false, fmt.Errorf("isset unable to use key of type %T as index", key)
		}
		if av.Len() > k {
			return true, nil
		}
	case reflect.Map:
		if kv.Type() == av.Type().Key() {
			return av.MapIndex(kv).IsValid(), nil
		}
	default:
		ns.deps.Log.Warnf("calling IsSet with unsupported type %q (%T) for key %v will always return false.\n", av.Kind(), c, key)
	}

	return false, nil
}

// Last returns the last limit items in the list l.
func (ns *Namespace) Last(limit any, l any) (any, error) {
	if limit == nil || l == nil {

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Pass an integer index when the first argument is a slice/array: `{{ isset $slice 0 }}`.
  2. If you meant to check a map key, verify the value actually is a map (`printf "%T"` it) — front matter lists vs maps are easy to confuse.
  3. Guard with a kind check: `{{ if reflect.IsMap $c }}{{ isset $c "key" }}{{ end }}`.

Example fix

<!-- before -->
{{ if isset .Params.tags "news" }}...{{ end }}
<!-- after: tags is a slice; use `in` for membership -->
{{ if in .Params.tags "news" }}...{{ end }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{/* ensure key is a scalar (string/int), not a slice or map */}}
{{ if or (reflect.IsSlice $key) (reflect.IsMap $key) }}
  {{ errorf "key must be a string or integer, got %T" $key }}
{{ end }}
{{ if isset $collection $key }}{{ index $collection $key }}{{ end }}

Type guard

{{/* narrow: strings index maps, ints index slices */}}
{{ $ok := or (eq (printf "%T" $key) "string") (eq (printf "%T" $key) "int") }}

Prevention

When it happens

Trigger: Calling `{{ isset .Slice "foo" }}` or `{{ isset $arr .SomeStringVar }}` where the first argument is an array/slice/channel and the key cannot be converted to an int.

Common situations: Templates written for a map (e.g. `.Params`) later applied to a slice; iterating mixed data from front matter or data files where a field is sometimes a map and sometimes a list; passing a page or dict as the key by mistake.

Related errors


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