{"record":{"id":"468114266d112458","repo":"gohugoio/hugo","slug":"start-argument-must-be-an-integer","errorCode":null,"errorMessage":"start argument must be an integer","messagePattern":"start argument must be an integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":399,"sourceCode":"// if length is given and is negative, then that many characters will be omitted from\n// the end of string.\nfunc (ns *Namespace) Substr(a any, nums ...any) (string, error) {\n\ts, err := cast.ToStringE(a)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tasRunes := []rune(s)\n\trlen := len(asRunes)\n\n\tvar start, length int\n\n\tswitch len(nums) {\n\tcase 0:\n\t\treturn \"\", errors.New(\"too few arguments\")\n\tcase 1:\n\t\tif start, err = cast.ToIntE(nums[0]); err != nil {\n\t\t\treturn \"\", errors.New(\"start argument must be an integer\")\n\t\t}\n\t\tlength = rlen\n\tcase 2:\n\t\tif start, err = cast.ToIntE(nums[0]); err != nil {\n\t\t\treturn \"\", errors.New(\"start argument must be an integer\")\n\t\t}\n\t\tif length, err = cast.ToIntE(nums[1]); err != nil {\n\t\t\treturn \"\", errors.New(\"length argument must be an integer\")\n\t\t}\n\tdefault:\n\t\treturn \"\", errors.New(\"too many arguments\")\n\t}\n\n\tif rlen == 0 {\n\t\treturn \"\", nil\n\t}\n\n\tif start < 0 {","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/strings/strings.go#L381-L417","documentation":"Thrown by the strings.Substr template function when called with one variadic argument that cannot be cast to an integer (the start position). Substr's signature is Substr(a any, nums ...any); with exactly one num, that num is treated as the start index and must be a whole number. Hugo surfaces this as a template rendering error with the message 'start argument must be an integer'.","triggerScenarios":"Calling {{ substr \"hello\" \"x\" }} or {{ \"hello\" | substr 2.5 }} or {{ substr .Title .SomeStringVar }} where the single num argument is a non-integer string, float, or nil.","commonSituations":"Passing a front matter value that was parsed as a string (e.g. a page parameter) instead of a number; using a computed value that resolves to a float; copy-pasting a PHP-style substr example with string offsets.","solutions":["Coerce the start argument to an integer before calling, e.g. {{ substr .Title (int .StartVar) }}.","Verify the value is numeric: {{ with .StartVar }}{{ if (eq (printf \"%T\" .) \"int\") }}...{{ end }}{{ end }}.","Fix the upstream data source so the parameter is stored as a number in front matter."],"exampleFix":"// before\n{{ substr .Title .Offset }}\n// after\n{{ substr .Title (int .Offset) }}","handlingStrategy":"validation","validationCode":"{{ $start := int .Offset }}\n{{ substr .Title $start }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always wrap numeric args in (int ...) when sourced from front matter.","Keep numeric page params as integers, not strings, in front matter."],"tags":["template-function","strings","substr","type-coercion","argument"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}