gohugoio/hugo · error
%q is not a valid duration unit
Error message
%q is not a valid duration unit
What it means
Hugo's `time.Duration` template function (alias `duration`) converts a number into a Go time.Duration using a unit name looked up in a fixed map (durationUnits in tpl/time/time.go). If the unit string passed as the first argument isn't one of the supported keys, the lookup fails and this error is returned. Only nanosecond/ns, microsecond/us/µs, millisecond/ms, second/s, minute/m, and hour/h are accepted.
Source
Thrown at tpl/time/time.go:143
"ms": time.Millisecond,
"second": time.Second,
"s": time.Second,
"minute": time.Minute,
"m": time.Minute,
"hour": time.Hour,
"h": time.Hour,
}
// Duration converts the given number to a time.Duration.
// Unit is one of nanosecond/ns, microsecond/us/µs, millisecond/ms, second/s, minute/m or hour/h.
func (ns *Namespace) Duration(unit any, number any) (time.Duration, error) {
unitStr, err := cast.ToStringE(unit)
if err != nil {
return 0, err
}
unitDuration, found := durationUnits[unitStr]
if !found {
return 0, fmt.Errorf("%q is not a valid duration unit", unit)
}
n, err := cast.ToInt64E(number)
if err != nil {
return 0, err
}
return time.Duration(n) * unitDuration, nil
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Use an exact supported unit: nanosecond/ns, microsecond/us, millisecond/ms, second/s, minute/m, hour/h — singular, lowercase.
- For days or weeks, multiply hours: `{{ duration "hour" (mul 24 7) }}`.
- Check argument order: unit comes first, number second (`duration "second" 60`).
Example fix
<!-- before -->
{{ duration "minutes" 5 }}
<!-- after -->
{{ duration "minute" 5 }} Defensive patterns
Strategy: validation
Validate before calling
{{ $unit := "days" }}
{{ $valid := slice "nanosecond" "microsecond" "millisecond" "second" "minute" "hour" }}
{{ if in $valid $unit }}{{ time.Duration $unit 3 }}{{ end }} Try / catch
{{ with try (time.Duration $unit $n) }}{{ if .Err }}{{ warnf "bad duration unit: %s" .Err }}{{ else }}{{ .Value }}{{ end }}{{ end }} Prevention
- Only pass one of the six supported units: nanosecond, microsecond, millisecond, second, minute, hour — there is no day/week/month unit
- Whitelist-check dynamic unit strings (e.g. from front matter or data files) before calling time.Duration
- Normalize unit strings with lower/trim before comparison
When it happens
Trigger: Calling `{{ duration "seconds" 60 }}` or `{{ time.Duration "days" 2 }}` in a template — any unit string not exactly matching a durationUnits key, including plural forms ("minutes", "hours"), capitalized forms ("Second"), or unsupported units ("day", "week", "d").
Common situations: Developers writing cache-busting or scheduling logic in templates who assume plural units work (`duration "minutes" 5`); trying to express days or weeks, which Go's time.Duration units don't include; passing the number and unit in swapped order so the number becomes the unit string.
Related errors
- errKeyIsEmptyString
- invalid arguments supplied to `time`
- errMustTwoNumbersError
- strings: negative Repeat count
- error correction level must be one of low, medium, quartile,
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/d384f635c32c96c7.json.
Report an issue: GitHub ↗.