{"id":"d617550af6c872a3","repo":"gohugoio/hugo","slug":"cannot-index-slice-array-with-nil","errorCode":null,"errorMessage":"cannot index slice/array with nil","messagePattern":"cannot index slice/array with nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/index.go","lineNumber":88,"sourceCode":"\n\tfor _, i := range indices {\n\t\tindex := reflect.ValueOf(i)\n\t\tvar isNil bool\n\t\tif v, isNil = hreflect.Indirect(v); isNil {\n\t\t\t// See issue 10489\n\t\t\t// This used to be an error.\n\t\t\treturn nil, nil\n\t\t}\n\t\tswitch v.Kind() {\n\t\tcase reflect.Array, reflect.Slice, reflect.String:\n\t\t\tvar x int64\n\t\t\tswitch index.Kind() {\n\t\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\t\tx = index.Int()\n\t\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:\n\t\t\t\tx = int64(index.Uint())\n\t\t\tcase reflect.Invalid:\n\t\t\t\treturn nil, errors.New(\"cannot index slice/array with nil\")\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"cannot index slice/array with type %s\", index.Type())\n\t\t\t}\n\t\t\tif x < 0 || x >= int64(v.Len()) {\n\t\t\t\t// We deviate from stdlib here.  Don't return an error if the\n\t\t\t\t// index is out of range.\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tv = v.Index(int(x))\n\t\tcase reflect.Map:\n\t\t\tindex, err := prepareArg(index, v.Type().Key())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tif x := v.MapIndex(index); x.IsValid() {\n\t\t\t\tv = x\n\t\t\t} else {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/index.go#L70-L106","documentation":"Inside `index`, when the indexed value is a slice, array, or string, the index must be an integer. A nil index has reflect.Kind Invalid, which cannot be converted to an integer position, so Hugo rejects it explicitly. This surfaces wrapped inside the \"index of type %T with args %v failed\" error.","triggerScenarios":"`{{ index $slice $i }}` where `$i` is nil — typically an unset variable, a missing `.Params` key, or a shortcode `.Get` that returned nothing. Only occurs when the container is a slice/array/string; nil keys on maps take a different path.","commonSituations":"Shortcodes using `index $args (.Get \"pos\")` when the attribute is omitted; templates reading an index from front matter that some pages don't define; loop variables shadowed or out of scope.","solutions":["Provide a default for the index: `{{ index $slice (default 0 $i) }}`.","Guard the lookup: `{{ with $i }}{{ index $slice . }}{{ end }}`.","Trace where the nil comes from (unset param, missing shortcode attribute) and fix the source data."],"exampleFix":"<!-- before -->\n{{ index $items (.Get \"n\") }}\n<!-- after -->\n{{ index $items (default 0 (.Get \"n\")) }}","handlingStrategy":"validation","validationCode":"{{ if ne $key nil }}{{ index $slice $key }}{{ end }}","typeGuard":"{{ $validKey := and (ne $key nil) (ge $key 0) (lt $key (len $slice)) }}","tryCatchPattern":"{{ with try (index $slice $key) }}{{ with .Err }}{{ warnf \"slice index failed: %s\" . }}{{ end }}{{ end }}","preventionTips":["Never pass a possibly-nil variable as a slice index — default it with `| default 0`","Slices need integer keys; nil keys only make sense for maps, and not here","Bounds-check with len before indexing user-derived positions"],"tags":["hugo","templates","index","nil"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}