{"id":"4f79ab9e3a8f18e9","repo":"gohugoio/hugo","slug":"too-few-arguments","errorCode":null,"errorMessage":"too few arguments","messagePattern":"too few arguments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":396,"sourceCode":"// To extract characters from the end of the string, use a negative start number.\n//\n// In addition, borrowing from the extended behavior described at http://php.net/substr,\n// 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","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/strings/strings.go#L378-L414","documentation":"Hugo's `strings.Substr` requires at least a start position after the string; with zero variadic arguments there is nothing to extract, so it fails fast with \"too few arguments\" rather than returning the whole string.","triggerScenarios":"Calling `substr` with only the string: `{{ substr \"hello\" }}`, or a pipeline like `{{ .Title | substr }}` where no start/length arguments are given.","commonSituations":"Confusing `substr` with functions that have sensible no-arg defaults; refactoring a template and dropping the index arguments; dynamically built calls where a param evaluated to nothing.","solutions":["Provide at least a start index: `{{ substr \"hello\" 1 }}`","Provide start and length for a bounded extract: `{{ substr \"hello\" 1 3 }}`","If you just wanted the whole string, drop the `substr` call entirely"],"exampleFix":"// before\n{{ substr .Title }}\n// after\n{{ substr .Title 0 10 }}","handlingStrategy":"validation","validationCode":"{{/* truncate needs at least a length: */}}\n{{ if and .len .text }}{{ truncate .len .text }}{{ end }}","typeGuard":null,"tryCatchPattern":"{{ with try (truncate .len .text) }}{{ if .Err }}{{ errorf \"truncate misuse: %s\" .Err }}{{ end }}{{ end }}","preventionTips":["Always pass both the length and the text — in pipe form `{{ .Summary | truncate 70 }}` the piped value supplies the text.","Verify optional params exist with `default` before building the call: `truncate (default 70 .Params.summaryLen) .Summary`.","Build with `hugo` in CI so arity errors fail the build rather than shipping."],"tags":["hugo","templates","strings","arguments"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}