gohugoio/hugo · error
cannot encode an empty string
Error message
cannot encode an empty string
What it means
Thrown by the images.QR template function when the text argument passed to it is an empty string. The QR encoder (rsc.io/qr) has nothing to encode, so Hugo rejects the input explicitly before attempting generation rather than producing a meaningless blank code. The check happens immediately after cast.ToStringE succeeds in tpl/images/images.go:142.
Solutions
- Guard with an {{ if qrText }} ... {{ end }} block around the images.QR call so empty values skip generation.
- Provide a fallback: {{ $text := .Param "qr_text" | default .Permalink }} before calling images.QR.
- Filter the source collection with where to exclude entries whose target field is empty before the QR loop.
- If the empty value is unexpected, log it ({{ warnf "empty QR text for %q" .Path }}) to find which content item is missing data.
Example fix
// before
{{ $qr := images.QR .Param "code" }}
// after
{{ $code := .Param "code" }}
{{ if $code }}
{{ $qr := images.QR $code }}
{{ end }} Defensive patterns
Strategy: validation
Validate before calling
// In a Hugo template, validate before calling images.QR:
{{ $text := .Param "qr_text" }}
{{ if $text }}
{{ $qr := images.QR $text }}
{{ end }} Type guard
// Go caller using the images.Namespace directly:
func nonEmptyString(v any) (string, bool) {
s, ok := v.(string)
return s, ok && s != ""
} Prevention
- Always gate images.QR behind an {{ if $text }} check.
- Provide a default that is guaranteed non-empty (e.g. .Permalink) when the primary source may be blank.
- Use {{ warnf }} to surface which content item produced an empty value during the build.
When it happens
Trigger: Calling {{ images.QR "" }} or {{ images.QR someVar }} where someVar evaluates to an empty string (e.g. an unset page param, an empty .Title, or a scratch/default that resolved to ""). Also when the first positional arg is whitespace-only but cast to a trimmed empty string.
Common situations: Looping over a collection where some entries have no URL/identifier and generating a QR code per entry; using {{ .Param "qr_text" }} without a default; reading from front matter that was left blank; migrating content where a field was renamed and old pages now resolve to empty.
Related errors
- scale must be an integer greater than or equal to 2
- error correction level must be one of low, medium…
- both count and seq must be provided
- cannot index slice/array with nil
- complement needs at least two arguments
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/e8783ed9958e92aa.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/images/images.go:143
Level string // error correction level; one of low, medium, quartile, or high
Scale int // number of image pixels per QR code module
TargetDir string // target directory relative to publishDir
}{
Level: qrDefaultErrorCorrectionLevel,
Scale: qrDefaultScale,
}
if len(args) == 0 || len(args) > 2 {
return nil, errors.New("requires 1 or 2 arguments")
}
text, err := cast.ToStringE(args[0])
if err != nil {
return nil, err
}
if text == "" {
return nil, errors.New("cannot encode an empty string")
}
if len(args) == 2 {
err := mapstructure.WeakDecode(args[1], &opts)
if err != nil {
return nil, err
}
}
level, ok := qrErrorCorrectionLevels[opts.Level]
if !ok {
return nil, errors.New("error correction level must be one of low, medium, quartile, or high")
}
if opts.Scale < 2 {
return nil, errors.New("scale must be an integer greater than or equal to 2")
}
View on GitHub (pinned to 52c9bd7908)