gohugoio/hugo · error
end argument must be integer
Error message
end argument must be integer
What it means
In `strings.SliceString`, the optional second index (end) is cast with `cast.ToIntE`. A value that can't be converted to an int aborts template execution with this error, keeping the half-open range semantics strict rather than silently defaulting.
Source
Thrown at tpl/strings/strings.go:335
// 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")
}
if argNum == 2 {
if argEnd < 0 || argEnd > len(asRunes) {
return "", errors.New("slice bounds out of range")
}
return string(asRunes[argStart:argEnd]), nilView on GitHub ↗ (pinned to 8a468df065)
Solutions
- Pass an integer end index: `{{ slicestr $s 0 3 }}`
- Coerce dynamic values with `int`: `{{ slicestr $s 0 (int .Params.end) }}`
- Omit the end argument entirely if you want to slice to the end of the string
Example fix
// before
{{ slicestr "BatMan" 0 "3" x }}
// after
{{ slicestr "BatMan" 0 3 }} Defensive patterns
Strategy: type-guard
Validate before calling
{{ $end := int (default (len .s) .end) }}
{{ substr .s 0 $end }} Type guard
{{ $end := .end }}{{ if $end }}{{ $end = int $end }}{{ end }} Try / catch
{{ with try (substr .s 0 .end) }}{{ if .Err }}{{ warnf "%s" .Err }}{{ else }}{{ .Value }}{{ end }}{{ end }} Prevention
- Cast the optional end/length argument with `int` before calling substr.
- Omit the end argument entirely when you want the rest of the string instead of passing nil or a non-integer sentinel.
- Treat values from .Params, environment, and data files as untyped — normalize them once at the top of the template.
When it happens
Trigger: Calling `slicestr` with three arguments where the third (end index) is non-numeric: `{{ slicestr "BatMan" 0 "end" }}`, or an end index sourced from a param/variable holding a non-numeric value or nil.
Common situations: End index read from front matter as a string; passing `len $s` results wrapped in unexpected types; copy-pasted examples where the end argument is a word; nil params on pages missing the field.
Related errors
- start 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/7335e6b7c7215494.json.
Report an issue: GitHub ↗.