gohugoio/hugo · error
can't index item of type %s
Error message
can't index item of type %s
What it means
Thrown inside doIndex when the item being indexed is reflect.Invalid-handled separately-or a kind that is neither Array, Slice, String, nor Map (e.g. struct, int, float, bool, func, chan). The item's reflect.Type is named via %s. This means the value itself is not indexable at all, regardless of the key supplied.
Source
Thrown at tpl/collections/index.go:113
return nil, nil
}
v = v.Index(int(x))
case reflect.Map:
index, err := prepareArg(index, v.Type().Key())
if err != nil {
return nil, err
}
if x := v.MapIndex(index); x.IsValid() {
v = x
} else {
v = reflect.Zero(v.Type().Elem())
}
case reflect.Invalid:
// the loop holds invariant: v.IsValid()
panic("unreachable")
default:
return nil, fmt.Errorf("can't index item of type %s", v.Type())
}
}
return v.Interface(), nil
}
// prepareArg checks if value can be used as an argument of type argType, and
// converts an invalid value to appropriate zero if possible.
//
// Copied from Go stdlib src/text/template/funcs.go.
func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) {
if !value.IsValid() {
if !canBeNil(argType) {
return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType)
}
value = reflect.Zero(argType)
}
if !value.Type().AssignableTo(argType) {
return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)View on GitHub (pinned to 52c9bd7908)
Solutions
- Use field/method access for structs: `{{ .Title }}` instead of `{{ index . "Title" }}`.
- Stop indexing once you reach a scalar leaf.
- Convert the value to a map if generic key access is required.
- Inspect the type named in the error to choose field vs index access.
Example fix
// before
{{ index .Page "Title" }}
// after
{{ .Page.Title }} Defensive patterns
Strategy: type-guard
Validate before calling
func isIndexableKind(v any) bool {
rv := reflect.ValueOf(v)
if !rv.IsValid() { return false }
switch rv.Kind() {
case reflect.Slice, reflect.Array, reflect.String, reflect.Map:
return true
}
return false
} Type guard
func isIndexableCollection(v any) bool {
return isIndexableKind(v)
} Prevention
- Use field/method access (`.Field`) for structs instead of index.
- Stop traversing once you reach a scalar leaf.
- Confirm the value is a map/slice/array before indexing.
- Inspect the named type in the error to choose access strategy.
When it happens
Trigger: Calling `{{ index 42 0 }}`, `{{ index $pageObject "Title" }}` (page is a struct, not indexable — use `.Title` field access instead), `{{ index 3.14 "x" }}`, or `{{ index $func 0 }}`. The default branch in doIndex's switch over v.Kind() catches all non-indexable kinds.
Common situations: Author assumes an object is a map when it is a struct (pages, resources are structs), or chains index past a scalar leaf. Common when traversing nested data where a path segment resolves to a primitive but indexing continues.
Related errors
- cannot index slice/array with type %s
- value has type %s; should be %s
- isset unable to use key of type %T as index
- type %T not supported
- arguments to complement must be slices or arrays
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/fc32b533e67ff320.
Report an issue: GitHub.