gohugoio/hugo · error
invalid type for comparison
Error message
invalid type for comparison
What it means
Defined as errBadComparisonType in tpl/internal/go_templates/texttemplate/funcs.go:402 and returned by the template comparison operators (eq, ne, lt, le, gt, ge). It fires when basicKind() cannot classify an operand (e.g. a struct, map, slice, or func) or when lt/le/gt/ge is applied to bool or complex values, which are not orderable. This is the underlying text/template engine reused by Hugo.
Source
Thrown at tpl/internal/go_templates/texttemplate/funcs.go:402
}
// or computes the Boolean OR of its arguments, returning
// the first true argument it encounters, or the last argument.
func or(arg0 reflect.Value, args ...reflect.Value) reflect.Value {
panic("unreachable") // implemented as a special case in evalCall
}
// not returns the Boolean negation of its argument.
func not(arg reflect.Value) bool {
return !truth(arg)
}
// Comparison.
// TODO: Perhaps allow comparison between signed and unsigned integers.
var (
errBadComparisonType = errors.New("invalid type for comparison")
errNoComparison = errors.New("missing argument for comparison")
)
type kind int
const (
invalidKind kind = iota
boolKind
complexKind
intKind
floatKind
stringKind
uintKind
)
func basicKind(v reflect.Value) (kind, error) {
switch v.Kind() {
case reflect.Bool:View on GitHub (pinned to 52c9bd7908)
Solutions
- Compare a comparable field: use .Date, .Weight, .RelPermalink, .Title, etc. instead of the whole object.
- For ordering, ensure both operands are bool/int/uint/float/string and the same kind (int vs uint has a special case, others must match).
- For equality on structs/maps, compare a unique key field or use a custom approach (e.g. .File.Path).
- Do not use lt/le/gt/ge on bool or complex values; convert booleans to ints if you need ordering.
Example fix
// before
{{ if lt .Page .OtherPage }}
// after
{{ if lt .Date .OtherPage.Date }} Defensive patterns
Strategy: validation
Validate before calling
// Compare a comparable field rather than whole objects:
{{ if lt .Date .OtherPage.Date }}...{{ end }}
// Avoid lt/le/gt/ge on bool or complex; for equality on primitives only. Type guard
// Go caller: only bool/int/uint/float/string/complex are comparable via basicKind.
func orderable(k reflect.Kind) bool {
switch k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.String:
return true
}
return false
} Prevention
- Never pass structs, maps, slices, or funcs to eq/lt/le/gt/ge.
- For ordering, restrict to int/uint/float/string of matching kinds.
- Compare a representative field (.Date, .Weight, .RelPermalink) instead of the whole object.
- Do not use lt/le/gt/ge on bool or complex values.
When it happens
Trigger: Writing {{ if lt .Page .OtherPage }} (comparing structs), {{ if lt $map1 $map2 }} (comparing maps), {{ if eq $slice1 $slice2 }} with non-comparable slices, or {{ if lt .Flag true }} (ordering booleans). Also comparing a struct field that is itself a non-basic type.
Common situations: Comparing page objects instead of a comparable field like .RelPermalink or .Date; assuming eq works on arbitrary structs; ordering booleans; comparing complex128 values.
Related errors
- need at least 2 arguments to append
- can't apply myself (no turtles allowed)
- can't iterate over a nil value
- can't find function {fname}
- called apply using {xt} as type {targ}
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/853c0d705e9e8b27.
Report an issue: GitHub.