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

  1. Read the appended 'failed: %s' suffix to identify the real cause (e.g. 'cannot index slice/array with type string').
  2. Match the key type to the collection: integer for slices/arrays, the map's declared key type for maps.
  3. Add a type guard or default before indexing: `{{ $v := default "" (index $m "k") }}`.
  4. 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

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


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)