{"record":{"id":"048d52dde38536d0","repo":"gohugoio/hugo","slug":"can-t-iterate-over-type","errorCode":null,"errorMessage":"can't iterate over {type}","messagePattern":"can't iterate over (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/collections.go","lineNumber":89,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif nv < 0 {\n\t\treturn nil, errors.New(\"sequence bounds out of range [\" + cast.ToString(nv) + \":]\")\n\t}\n\n\tlv := reflect.ValueOf(l)\n\tlv, isNil := hreflect.Indirect(lv)\n\tif isNil {\n\t\treturn nil, errors.New(\"can't iterate over a nil value\")\n\t}\n\n\tswitch lv.Kind() {\n\tcase reflect.Array, reflect.Slice, reflect.String:\n\t\t// okay\n\tdefault:\n\t\treturn nil, errors.New(\"can't iterate over \" + reflect.ValueOf(l).Type().String())\n\t}\n\n\tif nv >= lv.Len() {\n\t\treturn lv.Slice(0, 0).Interface(), nil\n\t}\n\n\treturn lv.Slice(nv, lv.Len()).Interface(), nil\n}\n\n// Delimit takes a given list l and returns a string delimited by sep.\n// If last is passed to the function, it will be used as the final delimiter.\nfunc (ns *Namespace) Delimit(ctx context.Context, l, sep any, last ...any) (string, error) {\n\td, err := cast.ToStringE(sep)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar dLast *string","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/collections.go#L71-L107","documentation":"After (collections.go:85-90) accepts only reflect.Array, Slice, or String. Any other Kind (map, struct, int, etc.) reaches the default branch and reports the actual type.","triggerScenarios":"{{ after 2 .Site.Data }} (map), {{ after 2 42 }} (int), {{ after 2 .Page }} (struct).","commonSituations":"Passing a dict/params map where a slice was expected; passing a single Page object instead of a page collection; passing a number.","solutions":["Pass a slice/array/string, not a map or scalar","If you have a map, extract a slice first (e.g. its values or a known sub-collection)","Use .Pages instead of .Page for collections"],"exampleFix":"// before\n{{ after 2 .Params }}\n// after\n{{ after 2 .Pages }}","handlingStrategy":"type-guard","validationCode":"{{ if reflect.IsSlice .Pages }}\n  {{ after 2 .Pages }}\n{{ end }}","typeGuard":"{{/* Go-side */}}\nfunc isIteratable(v any) bool {\n  k := reflect.TypeOf(v).Kind()\n  return k == reflect.Slice || k == reflect.Array || k == reflect.String\n}","tryCatchPattern":null,"preventionTips":["Pass only slices/arrays/strings to after","Use .Pages (collection) not .Page (single)","Convert maps to a sorted slice before slicing"],"tags":["hugo","go-template","collections","type-mismatch"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}