{"record":{"id":"6ccbd92065fec36f","repo":"gohugoio/hugo","slug":"index-of-type-t-with-args-v-failed-s","errorCode":null,"errorMessage":"index of type %T with args %v failed: %s","messagePattern":"index of type %T with args (.+?) failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/index.go","lineNumber":37,"sourceCode":"\t\"reflect\"\n\n\t\"github.com/spf13/cast\"\n\n\t\"github.com/gohugoio/hugo/common/hmaps\"\n\t\"github.com/gohugoio/hugo/common/hreflect\"\n)\n\n// Index returns the result of indexing its first argument by the following\n// arguments. Thus \"index x 1 2 3\" is, in Go syntax, x[1][2][3]. Each\n// indexed item must be a map, slice, or array.\n//\n// Adapted from Go stdlib src/text/template/funcs.go.\n//\n// We deviate from the stdlib mostly because of https://github.com/golang/go/issues/14751.\nfunc (ns *Namespace) Index(item any, args ...any) (any, error) {\n\tv, err := ns.doIndex(item, args...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"index of type %T with args %v failed: %s\", item, args, err)\n\t}\n\treturn v, nil\n}\n\nfunc (ns *Namespace) doIndex(item any, args ...any) (any, error) {\n\t// TODO(moorereason): merge upstream changes.\n\tv := reflect.ValueOf(item)\n\tif !v.IsValid() {\n\t\t// See issue 10489\n\t\t// This used to be an error.\n\t\treturn nil, nil\n\t}\n\n\tvar indices []any\n\n\tif len(args) == 1 {\n\t\tv := reflect.ValueOf(args[0])\n\t\tif v.Kind() == reflect.Slice {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/index.go#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{{ index $slice \"key\" }}\n// after\n{{ index $slice 0 }}","handlingStrategy":"try-catch","validationCode":"// Pre-validate indexability to avoid the wrapped error.\nfunc safeIndex(item any, args ...any) (any, error) {\n    v := reflect.ValueOf(item)\n    if !v.IsValid() { return nil, nil }\n    for _, a := range args {\n        switch v.Kind() {\n        case reflect.Slice, reflect.Array, reflect.String:\n            i, err := cast.ToIntE(a)\n            if err != nil { return nil, nil }\n            if i < 0 || i >= v.Len() { return nil, nil }\n            v = v.Index(i)\n        case reflect.Map:\n            k := reflect.ValueOf(a)\n            if !k.IsValid() || !k.Type().AssignableTo(v.Type().Key()) { return nil, nil }\n            x := v.MapIndex(k)\n            if !x.IsValid() { return reflect.Zero(v.Type().Elem()).Interface(), nil }\n            v = x\n        default:\n            return nil, nil\n        }\n    }\n    return v.Interface(), nil\n}","typeGuard":"func isIndexable(v any) bool {\n    rv := reflect.ValueOf(v)\n    if !rv.IsValid() { return false }\n    switch rv.Kind() {\n    case reflect.Slice, reflect.Array, reflect.String, reflect.Map:\n        return true\n    }\n    return false\n}","tryCatchPattern":"// In Go caller code:\nresult, err := ns.Index(item, args...)\nif err != nil {\n    // err already includes type + args; log and degrade gracefully\n    return nil, err\n}","preventionTips":["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."],"tags":["go","hugo","template","collections","index","wrapper-error"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}