{"record":{"id":"cb550488d4006ef6","repo":"gohugoio/hugo","slug":"slice-bounds-out-of-range","errorCode":null,"errorMessage":"slice bounds out of range","messagePattern":"slice bounds out of range","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":346,"sourceCode":"\tif argNum > 0 {\n\t\tif argStart, err = cast.ToIntE(startEnd[0]); err != nil {\n\t\t\treturn \"\", errors.New(\"start argument must be integer\")\n\t\t}\n\t}\n\tif argNum > 1 {\n\t\tif argEnd, err = cast.ToIntE(startEnd[1]); err != nil {\n\t\t\treturn \"\", errors.New(\"end argument must be integer\")\n\t\t}\n\t}\n\n\tif argNum > 2 {\n\t\treturn \"\", errors.New(\"too many arguments\")\n\t}\n\n\tasRunes := []rune(aStr)\n\n\tif argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) {\n\t\treturn \"\", errors.New(\"slice bounds out of range\")\n\t}\n\n\tif argNum == 2 {\n\t\tif argEnd < 0 || argEnd > len(asRunes) {\n\t\t\treturn \"\", errors.New(\"slice bounds out of range\")\n\t\t}\n\t\treturn string(asRunes[argStart:argEnd]), nil\n\t} else if argNum == 1 {\n\t\treturn string(asRunes[argStart:]), nil\n\t} else {\n\t\treturn string(asRunes[:]), nil\n\t}\n}\n\n// Split slices an input string into all substrings separated by delimiter.\nfunc (ns *Namespace) Split(a any, delimiter string) ([]string, error) {\n\taStr, err := cast.ToStringE(a)\n\tif err != nil {","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/strings/strings.go#L328-L364","documentation":"Thrown by strings.SliceString when the start index is negative or greater than/equal to the rune length of the string. The check is argStart < 0 || argStart >= len(asRunes), operating on rune count (not byte count), so multibyte strings are handled correctly.","triggerScenarios":"Calling {{ strings.SliceString \"abc\" 5 }} (start beyond end), {{ strings.SliceString \"abc\" -1 }} (negative), or using a start index larger than the string's rune length.","commonSituations":"Indices computed from .Params that exceed string length on short strings; off-by-one errors; negative indices (SliceString does NOT support negative indexing, unlike Substr).","solutions":["Clamp the start to the valid range: {{ $start = math.Min (float $start) (float (strings.RuneCount $s)) }} then cast to int.","Use strings.Substr instead if you need negative indexing from the end.","Guard with a length check before slicing."],"exampleFix":"// before\n{{ strings.SliceString $s $start }}\n// after\n{{ if lt $start (strings.RuneCount $s) }}{{ strings.SliceString $s $start }}{{ end }}","handlingStrategy":"validation","validationCode":"{{ $n := strings.RuneCount $s }}\n{{ if and (ge $start 0) (lt $start $n) }}{{ strings.SliceString $s $start }}{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the start index is within [0, runeCount) before slicing.","Use strings.Substr if you need negative indexing.","Remember bounds use rune count, not byte count."],"tags":["template","strings","bounds","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}