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
- Pass an integer (or numeric string) as the start index, e.g. `{{ slicestr $s 1 }}`
- If the value comes from front matter/params, convert it explicitly with `int`, e.g. `{{ slicestr $s (int .Params.start) }}`
- 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
- Cast site params and front matter values with `int` before passing them as substr's start argument — values from YAML/JSON front matter or URL params often arrive as strings or float64.
- Never pass floats with fractional parts; substr requires an exact integer.
- Add a default: `int (default 0 .start)` so nil params don't reach the call.
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
- end argument must be integer
- length argument must be an integer
- symdiff: failed to convert value: %w
- the math.Abs function requires a numeric argument
- Ceil operator can't be used with non-float value
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/b97cbb66ca8bb2d5.json.
Report an issue: GitHub ↗.