gohugoio/hugo · error

text must be a string

Error message

text must be a string

What it means

Thrown by strings.Truncate when the text argument (resolved from options) cannot be cast to a string (tpl/strings/truncate.go:71-73). After the length and optional ellipsis are validated, the text must be string-convertible.

Solutions

  1. Pass a string field: {{ truncate 50 .Title }} instead of {{ truncate 50 . }}.
  2. Render complex objects first, e.g. with .Plain or .Summary.
  3. Default nil: {{ truncate 50 (default "" .MaybeText) }}.

Example fix

// before
{{ truncate 50 . }}
// after
{{ truncate 50 .Title }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ with .Title }}{{ truncate 50 . }}{{ end }}

Type guard

{{/* guardString ensures a string-castable value */}}
{{ define "guardString" }}{{ if . }}{{ if (eq (printf "%T" .) "string") }}{{ . }}{{ else }}{{ plainify . }}{{ end }}{{ end }}{{ end }}

Prevention

When it happens

Trigger: Calling {{ truncate 50 .SomeNonStringableValue }} where the value is a struct, map, slice, or nil that cast.ToStringE rejects.

Common situations: Passing a complex object (e.g. a Page or slice) instead of a field like .Title; nil values from missing params; unexpected types from resources or data files.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/664305ca40fc71e0. Report an issue: GitHub.

Appendix: source

Thrown at tpl/strings/truncate.go:73

	case 1:
		textParam = options[0]
		ellipsis = " …"
	case 2:
		textParam = options[1]
		ellipsis, err = cast.ToStringE(options[0])
		if err != nil {
			return "", errors.New("ellipsis must be a string")
		}
		if _, ok := options[0].(template.HTML); !ok {
			ellipsis = html.EscapeString(ellipsis)
		}
	default:
		return "", errors.New("too many arguments passed to truncate")
	}

	text, err := cast.ToStringE(textParam)
	if err != nil {
		return "", errors.New("text must be a string")
	}

	_, isHTML := textParam.(template.HTML)

	if utf8.RuneCountInString(text) <= length {
		if isHTML {
			return template.HTML(text), nil
		}
		return template.HTML(html.EscapeString(text)), nil
	}

	tags := []htmlTag{}
	var lastWordIndex, lastNonSpace, currentLen, endTextPos, nextTag int

	for i, r := range text {
		if i < nextTag {
			continue
		}

View on GitHub (pinned to 52c9bd7908)