gohugoio/hugo · error

Round operator can't be used with non-float value

Error message

Round operator can't be used with non-float value

What it means

Hugo's `math.Round` casts its single argument to float64 via `cast.ToFloat64E` and then rounds half away from zero using an internal `_round` helper. When the argument isn't convertible to a float (non-numeric string, nil, composite value), Hugo returns this error.

Source

Thrown at tpl/math/math.go:225

// Product returns the product of all numbers in inputs. Any slices in inputs are flattened.
func (ns *Namespace) Product(inputs ...any) (product float64, err error) {
	fn := func(x, y float64) float64 {
		return x * y
	}
	return ns.applyOpToScalarsOrSlices("Product", fn, inputs...)
}

// Rand returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
func (ns *Namespace) Rand() float64 {
	return rand.Float64()
}

// Round returns the integer nearest to n, rounding half away from zero.
func (ns *Namespace) Round(n any) (float64, error) {
	xf, err := cast.ToFloat64E(n)
	if err != nil {
		return 0, errors.New("Round operator can't be used with non-float value")
	}

	return _round(xf), nil
}

// Sin returns the sine of the radian argument n.
func (ns *Namespace) Sin(n any) (float64, error) {
	af, err := cast.ToFloat64E(n)
	if err != nil {
		return 0, errors.New("requires a numeric argument")
	}
	return math.Sin(af), nil
}

// Sqrt returns the square root of the number n.
func (ns *Namespace) Sqrt(n any) (float64, error) {
	af, err := cast.ToFloat64E(n)
	if err != nil {

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Round before formatting, not after: keep the value numeric through the pipeline and apply `printf`/`lang.FormatNumber` last.
  2. Cast explicitly: `{{ math.Round (float $v) }}`.
  3. Default missing params: `{{ math.Round (default 0.0 .Params.score) }}`.
  4. Strip units from data values or store them as plain numbers.

Example fix

<!-- before -->
{{ math.Round (printf "%.2f" $ratio) }}
<!-- after -->
{{ printf "%.2f" (math.Round $ratio) }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ math.Round (float $x) }}

Type guard

func toFloat(v any) (float64, bool) {
    f, err := cast.ToFloat64E(v)
    return f, err == nil
}

Try / catch

if _, err := ns.Round(x); err != nil {
    // value wasn't float-convertible
}

Prevention

When it happens

Trigger: `{{ math.Round X }}` where X is nil or a non-numeric string: `{{ math.Round "1.5em" }}`, `{{ math.Round .Params.score }}` with a missing param, or rounding the output of a string-producing function like `printf` without converting back to a number.

Common situations: Rounding computed values that were formatted to strings earlier in the pipeline (e.g. via `printf "%.2f"`); front-matter numbers stored with units ("3.5s"); data-file values quoted as strings; nil from absent `.Params`/`.Site.Params` keys.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/3bed0b9c9eb84709.json. Report an issue: GitHub ↗.