{"id":"7335e6b7c7215494","repo":"gohugoio/hugo","slug":"end-argument-must-be-integer","errorCode":null,"errorMessage":"end argument must be integer","messagePattern":"end argument must be integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":335,"sourceCode":"// The end index can be omitted, it defaults to the string's length.\nfunc (ns *Namespace) SliceString(a any, startEnd ...any) (string, error) {\n\taStr, err := cast.ToStringE(a)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar argStart, argEnd int\n\n\targNum := len(startEnd)\n\n\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","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/strings/strings.go#L317-L353","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n{{ slicestr \"BatMan\" 0 \"3\" x }}\n// after\n{{ slicestr \"BatMan\" 0 3 }}","handlingStrategy":"type-guard","validationCode":"{{ $end := int (default (len .s) .end) }}\n{{ substr .s 0 $end }}","typeGuard":"{{ $end := .end }}{{ if $end }}{{ $end = int $end }}{{ end }}","tryCatchPattern":"{{ with try (substr .s 0 .end) }}{{ if .Err }}{{ warnf \"%s\" .Err }}{{ else }}{{ .Value }}{{ end }}{{ end }}","preventionTips":["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."],"tags":["hugo","templates","go","type-conversion","strings"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}