{"id":"d98e06eef1d96908","repo":"gohugoio/hugo","slug":"length-argument-must-be-an-integer","errorCode":null,"errorMessage":"length argument must be an integer","messagePattern":"length argument must be an integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":407,"sourceCode":"\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 {\n\t\tstart += rlen\n\t}\n\n\t// start was originally negative beyond rlen\n\tif start < 0 {\n\t\tstart = 0\n\t}\n","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/strings/strings.go#L389-L425","documentation":"When `substr` is called with two extra arguments (start and length), the length is converted with `cast.ToIntE`. A length value that can't be cast to an int — a non-numeric string, map, slice, or nil — produces this error, since Hugo won't guess how many characters you meant.","triggerScenarios":"`{{ substr \"hello\" 0 \"abc\" }}`, or a length sourced from `.Params`/`site.Params` that holds a non-numeric string or is unset on some pages.","commonSituations":"Summary-length settings stored as strings like \"30 chars\" in config; passing the ellipsis or suffix string in the length position; nil front-matter fields on a subset of pages breaking only those builds.","solutions":["Pass an integer length: `{{ substr $s 0 30 }}`","Coerce config/param values: `{{ substr $s 0 (int site.Params.summaryLength) }}`","Guard optional params with `with`/`default`: `{{ substr $s 0 (default 30 .Params.len) }}`"],"exampleFix":"// before\n{{ substr .Summary 0 .Params.len }}  <!-- len: \"thirty\" -->\n// after\n{{ substr .Summary 0 (int (default 30 .Params.len)) }}","handlingStrategy":"type-guard","validationCode":"{{ $n := int (default 70 site.Params.truncateLen) }}\n{{ truncate $n .Summary }}","typeGuard":"{{ $n := .Params.maxLen }}{{ if $n }}{{ $n = int $n }}{{ else }}{{ $n = 70 }}{{ end }}","tryCatchPattern":"{{ with try (truncate .n .text) }}{{ if .Err }}{{ warnf \"%s\" .Err }}{{ .text }}{{ else }}{{ .Value }}{{ end }}{{ end }}","preventionTips":["Cast config-sourced lengths with `int` — TOML gives int64, YAML strings stay strings, JSON numbers arrive as float64.","Keep the length as a literal in the template when it doesn't need to be configurable.","Normalize all numeric params once in a partial and pass typed values downward."],"tags":["hugo","templates","go","type-conversion","strings"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}