gohugoio/hugo · error
index of type %T with args
Error message
index of type %T with args %v failed: %s
What it means
Wrapping error from Namespace.Index: any failure inside doIndex is reformatted to include the original item's type (%T) and the index args (%v) for diagnostics. It is a context-additive wrapper; the underlying cause string is appended after 'failed:'. Common underlying causes are nil-indexing, non-integer indices on slices, key-type mismatches on maps, or indexing a non-indexable type.
Solutions
- Read the appended 'failed: %s' suffix to identify the real cause (e.g. 'cannot index slice/array with type string').
- Match the key type to the collection: integer for slices/arrays, the map's declared key type for maps.
- Add a type guard or default before indexing: `{{ $v := default "" (index $m "k") }}`.
- Use Params.GetNested-style dotted access if the item is hmaps.Params.
Example fix
// before
{{ index $slice "key" }}
// after
{{ index $slice 0 }} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate indexability to avoid the wrapped error.
func safeIndex(item any, args ...any) (any, error) {
v := reflect.ValueOf(item)
if !v.IsValid() { return nil, nil }
for _, a := range args {
switch v.Kind() {
case reflect.Slice, reflect.Array, reflect.String:
i, err := cast.ToIntE(a)
if err != nil { return nil, nil }
if i < 0 || i >= v.Len() { return nil, nil }
v = v.Index(i)
case reflect.Map:
k := reflect.ValueOf(a)
if !k.IsValid() || !k.Type().AssignableTo(v.Type().Key()) { return nil, nil }
x := v.MapIndex(k)
if !x.IsValid() { return reflect.Zero(v.Type().Elem()).Interface(), nil }
v = x
default:
return nil, nil
}
}
return v.Interface(), nil
} Type guard
func isIndexable(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
} Try / catch
// In Go caller code:
result, err := ns.Index(item, args...)
if err != nil {
// err already includes type + args; log and degrade gracefully
return nil, err
} Prevention
- Match key type to collection kind: int for slices/arrays, map key type for maps.
- Use the appended 'failed:' cause to diagnose the real issue.
- Default missing keys before indexing.
- For Params maps, prefer dotted GetNested access.
When it happens
Trigger: Any `{{ index $x $badKey }}` that fails internally — e.g. `{{ index $slice "a" }}` (string key on slice), `{{ index $struct 0 }}` (indexing a struct), `{{ index $map $nilKey }}` (nil key for non-nillable key type), or `{{ index $num 0 }}` (indexing a number). The wrapper surfaces the item type and the args that triggered it.
Common situations: Template author chains `index` over heterogeneous data, uses a computed key whose type doesn't match, or pipes params expecting a map but getting a slice. Most common when front matter is a Params map but a nested path resolves to a non-indexable scalar.
Related errors
- can't index item of type
- cannot index slice/array with type
- symdiff: failed to convert value
- value has type ; should be
- value is nil; should be of type
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/6ccbd92065fec36f.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/collections/index.go:37
"reflect"
"github.com/spf13/cast"
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hreflect"
)
// 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.
//
// Adapted from Go stdlib src/text/template/funcs.go.
//
// We deviate from the stdlib mostly because of https://github.com/golang/go/issues/14751.
func (ns *Namespace) Index(item any, args ...any) (any, error) {
v, err := ns.doIndex(item, args...)
if err != nil {
return nil, fmt.Errorf("index of type %T with args %v failed: %s", item, args, err)
}
return v, nil
}
func (ns *Namespace) doIndex(item any, args ...any) (any, error) {
// TODO(moorereason): merge upstream changes.
v := reflect.ValueOf(item)
if !v.IsValid() {
// See issue 10489
// This used to be an error.
return nil, nil
}
var indices []any
if len(args) == 1 {
v := reflect.ValueOf(args[0])
if v.Kind() == reflect.Slice {View on GitHub (pinned to 52c9bd7908)