{"id":"8fd4b9f09596b5dd","repo":"gohugoio/hugo","slug":"truncate-requires-a-length-and-a-string","errorCode":null,"errorMessage":"truncate requires a length and a string","messagePattern":"truncate requires a length and a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/truncate.go","lineNumber":54,"sourceCode":"\ntype htmlTag struct {\n\tname    string\n\tpos     int\n\topenTag bool\n}\n\n// Truncate truncates the string in s to the specified length.\nfunc (ns *Namespace) Truncate(s any, options ...any) (template.HTML, error) {\n\tlength, err := cast.ToIntE(s)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvar textParam any\n\tvar ellipsis string\n\n\tswitch len(options) {\n\tcase 0:\n\t\treturn \"\", errors.New(\"truncate requires a length and a string\")\n\tcase 1:\n\t\ttextParam = options[0]\n\t\tellipsis = \" …\"\n\tcase 2:\n\t\ttextParam = options[1]\n\t\tellipsis, err = cast.ToStringE(options[0])\n\t\tif err != nil {\n\t\t\treturn \"\", errors.New(\"ellipsis must be a string\")\n\t\t}\n\t\tif _, ok := options[0].(template.HTML); !ok {\n\t\t\tellipsis = html.EscapeString(ellipsis)\n\t\t}\n\tdefault:\n\t\treturn \"\", errors.New(\"too many arguments passed to truncate\")\n\t}\n\n\ttext, err := cast.ToStringE(textParam)\n\tif err != nil {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/strings/truncate.go#L36-L72","documentation":"Hugo's `truncate` takes the length first, then optionally an ellipsis, then the text. If only the length is supplied and no text argument follows (zero options), there is nothing to truncate, so it errors out. Note the piped value counts as the final argument.","triggerScenarios":"`{{ truncate 30 }}` with no text and nothing piped in, or building the call dynamically so the text argument ends up missing.","commonSituations":"Forgetting that argument order is length-first (`truncate 30 .Summary`, not `truncate .Summary 30` — the latter fails earlier at the int cast); dropping the piped value when refactoring `{{ .Summary | truncate 30 }}`; partials called without the expected text parameter.","solutions":["Add the text argument: `{{ truncate 30 .Summary }}` or pipe it: `{{ .Summary | truncate 30 }}`","Check the argument order — the length must come first","If the text can be empty/nil on some pages, wrap in `{{ with .Summary }}{{ truncate 30 . }}{{ end }}`"],"exampleFix":"// before\n{{ truncate 30 }}\n// after\n{{ truncate 30 .Summary }}","handlingStrategy":"validation","validationCode":"{{ if and (isset . \"len\") .text }}\n  {{ truncate (int .len) (string .text) }}\n{{ end }}","typeGuard":"{{/* ensure first arg is a number, last is a string */}}\n{{ $ok := and (in (slice \"int\" \"int64\" \"float64\") (printf \"%T\" .len)) (eq (printf \"%T\" .text) \"string\") }}","tryCatchPattern":"{{ with try (truncate .len .text) }}{{ if .Err }}{{ warnf \"truncate: %s\" .Err }}{{ .text }}{{ else }}{{ .Value }}{{ end }}{{ end }}","preventionTips":["Pass arguments in order: length first, optional ellipsis, string last — reversing them triggers this error.","Coerce with `int` and `string` when values come from front matter or data files.","Use the pipe idiom `{{ .Summary | truncate 70 }}` so the string is always supplied."],"tags":["hugo","templates","truncate","arguments"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}