gohugoio/hugo · error

start argument must be integer

Error message

start argument must be integer

What it means

Hugo's `strings.SliceString` template function converts its optional first index argument with `cast.ToIntE`. If the value passed as the start index cannot be cast to an int (e.g. a string like "abc", a slice, or nil), the function fails with this error instead of guessing a default.

Source

Thrown at tpl/strings/strings.go:330

	return replacer.Replace(ss), nil
}

// SliceString slices a string by specifying a half-open range with
// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
// The end index can be omitted, it defaults to the string's length.
func (ns *Namespace) SliceString(a any, startEnd ...any) (string, error) {
	aStr, err := cast.ToStringE(a)
	if err != nil {
		return "", err
	}

	var argStart, argEnd int

	argNum := len(startEnd)

	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")
	}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Pass an integer (or numeric string) as the start index, e.g. `{{ slicestr $s 1 }}`
  2. If the value comes from front matter/params, convert it explicitly with `int`, e.g. `{{ slicestr $s (int .Params.start) }}`
  3. Guard against unset params: `{{ with .Params.start }}{{ slicestr $s (int .) }}{{ end }}`

Example fix

// before
{{ slicestr "BatMan" "3"x }}
{{ slicestr .Title .Params.start }}  <!-- start is "two" -->
// after
{{ slicestr "BatMan" 3 }}
{{ slicestr .Title (int .Params.start) }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ $start := .start }}
{{ if ne (printf "%T" $start) "int" }}{{ $start = int $start }}{{ end }}
{{ substr .s $start }}

Type guard

{{/* narrow to int before calling substr */}}
{{ $start := int (default 0 .start) }}

Try / catch

{{ with try (substr .s .start) }}{{ if .Err }}{{ warnf "substr failed: %s" .Err }}{{ else }}{{ .Value }}{{ end }}{{ end }}

Prevention

When it happens

Trigger: Calling `slicestr` in a Hugo template with a non-integer start value: `{{ slicestr "BatMan" "x" }}`, or passing a template variable/param that resolves to a non-numeric string, map, or nil as the second argument.

Common situations: Site params read from front matter or config as strings that aren't numeric; accidentally passing the substring instead of an index; a `.Params` value that is unset (nil); confusing `slicestr` argument order with other functions.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/b97cbb66ca8bb2d5.json. Report an issue: GitHub ↗.