gohugoio/hugo · error

slice bounds out of range

Error message

slice bounds out of range

What it means

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.

Solutions

  1. Clamp the start to the valid range: {{ $start = math.Min (float $start) (float (strings.RuneCount $s)) }} then cast to int.
  2. Use strings.Substr instead if you need negative indexing from the end.
  3. Guard with a length check before slicing.

Example fix

// before
{{ strings.SliceString $s $start }}
// after
{{ if lt $start (strings.RuneCount $s) }}{{ strings.SliceString $s $start }}{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

{{ $n := strings.RuneCount $s }}
{{ if and (ge $start 0) (lt $start $n) }}{{ strings.SliceString $s $start }}{{ end }}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/cb550488d4006ef6. Report an issue: GitHub.

Appendix: source

Thrown at tpl/strings/strings.go:346

	if argNum > 0 {
		if argStart, err = cast.ToIntE(startEnd[0]); err != nil {
			return "", errors.New("start argument must be integer")
		}
	}
	if argNum > 1 {
		if argEnd, err = cast.ToIntE(startEnd[1]); err != nil {
			return "", errors.New("end argument must be integer")
		}
	}

	if argNum > 2 {
		return "", errors.New("too many arguments")
	}

	asRunes := []rune(aStr)

	if argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) {
		return "", errors.New("slice bounds out of range")
	}

	if argNum == 2 {
		if argEnd < 0 || argEnd > len(asRunes) {
			return "", errors.New("slice bounds out of range")
		}
		return string(asRunes[argStart:argEnd]), nil
	} else if argNum == 1 {
		return string(asRunes[argStart:]), nil
	} else {
		return string(asRunes[:]), nil
	}
}

// Split slices an input string into all substrings separated by delimiter.
func (ns *Namespace) Split(a any, delimiter string) ([]string, error) {
	aStr, err := cast.ToStringE(a)
	if err != nil {

View on GitHub (pinned to 52c9bd7908)