gohugoio/hugo · error
union does not support slices or arrays of uncomparable type
Error message
union does not support slices or arrays of uncomparable types
What it means
`union` deduplicates elements using them as map keys, which requires every element to be comparable per Go's rules. If an element in the first slice has an uncomparable type (slice, map, or func — including such values inside `[]any`), Hugo returns this error instead of panicking on the map insert.
Source
Thrown at tpl/collections/collections.go:672
case reflect.Array, reflect.Slice:
ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[any]bool)}
if l1v.Type() != l2v.Type() &&
l1v.Type().Elem().Kind() != reflect.Interface &&
l2v.Type().Elem().Kind() != reflect.Interface {
return ins.r.Interface(), nil
}
var (
l1vv reflect.Value
isNil bool
)
for i := range l1v.Len() {
l1vv, isNil = hreflect.Indirect(l1v.Index(i))
if !l1vv.Type().Comparable() {
return []any{}, errors.New("union does not support slices or arrays of uncomparable types")
}
if !isNil {
ins.appendIfNotSeen(l1vv)
}
}
if !l1vv.IsValid() {
// The first slice may be empty. Pick the first value of the second
// to use as a prototype.
if l2v.Len() > 0 {
l1vv = l2v.Index(0)
}
}
for j := range l2v.Len() {
l2vv := l2v.Index(j)
typ := l1vv.Type()View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Union only slices of comparable elements (strings, numbers, pages/pointers).
- For lists of maps, extract a comparable key first (e.g. `apply` to pull out an id/name), union those, then look entries back up.
- Alternatively concatenate with `append` and dedupe with `uniq` on a comparable projection.
Example fix
<!-- before -->
{{ $all := union $listOfDicts1 $listOfDicts2 }}
<!-- after: union comparable keys instead -->
{{ $keys := union (apply $listOfDicts1 "index" "." "id") (apply $listOfDicts2 "index" "." "id") }} Defensive patterns
Strategy: type-guard
Validate before calling
{{/* union requires comparable element types — scalars, not maps/slices */}}
{{ $ok := true }}
{{ range $a }}{{ if or (reflect.IsMap .) (reflect.IsSlice .) }}{{ $ok = false }}{{ end }}{{ end }}
{{ if $ok }}{{ $u := union $a $b }}{{ end }} Type guard
{{ $comparable := not (or (reflect.IsMap (index $a 0)) (reflect.IsSlice (index $a 0))) }} Prevention
- Use union only on slices of comparable values (strings, numbers) or Pages — not slices of maps/slices.
- For page collections, union works because Pages compare by identity; prefer it over hand-built dict lists.
- When merging lists of dicts, key them by a unique scalar field and union the keys instead.
When it happens
Trigger: `{{ union $a $b }}` where `$a` contains nested slices or maps, e.g. `union (slice (slice 1 2)) (slice (slice 3))` or unioning lists of dicts built with `dict`.
Common situations: Unioning lists of front-matter maps (each entry is a `map[string]any`); merging nested data-file structures; combining `slice`-of-`slice` groupings from `group` or `where` results.
Related errors
- arguments to complement must be slices or arrays
- %s isn't a key of map type %s
- %s is neither a struct field, a method nor a map element of
- type %T not supported in Resource transformations
- destination must be a map, got %T
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/c8aff4eb1418b4f0.json.
Report an issue: GitHub ↗.