gohugoio/hugo · error
symdiff: failed to convert value: %w
Error message
symdiff: failed to convert value: %w
What it means
`collections.SymDiff` builds its result slice with the element type of the first slice argument, and converts each kept element to that type via `convertValue` (tpl/collections/symdiff.go:55-58). This error wraps a conversion failure: an element from the second collection cannot be represented as the first collection's element type, so a coherent result slice cannot be constructed.
Source
Thrown at tpl/collections/symdiff.go:57
v := reflect.ValueOf(s)
switch v.Kind() {
case reflect.Array, reflect.Slice:
if i == 0 {
sliceType := v.Type()
sliceElemType = sliceType.Elem()
slice = reflect.MakeSlice(sliceType, 0, 0)
}
for i := range v.Len() {
ev, _ := hreflect.Indirect(v.Index(i))
key := normalize(ev)
// Append if the key is not in their intersection.
if ids1[key] != ids2[key] {
v, err := convertValue(ev, sliceElemType)
if err != nil {
return nil, fmt.Errorf("symdiff: failed to convert value: %w", err)
}
slice = reflect.Append(slice, v)
}
}
default:
return nil, fmt.Errorf("arguments to symdiff must be slices or arrays")
}
}
return slice.Interface(), nil
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Make both collections the same element type before diffing — e.g. map both to strings or both to pages.
- When comparing pages, diff the page collections directly (`.Pages | symdiff $other.Pages`) rather than mixing pages with scalars.
- For mixed data, normalize with `apply` or a range that builds uniform slices, then symdiff those.
Example fix
<!-- before: pages vs strings -->
{{ $d := slice "a" "b" | symdiff .Pages }}
<!-- after: compare like with like -->
{{ $titles := slice }}{{ range .Pages }}{{ $titles = $titles | append .Title }}{{ end }}
{{ $d := slice "a" "b" | symdiff $titles }} Defensive patterns
Strategy: validation
Validate before calling
{{/* ensure element types are comparable/convertible across the slices */}}
{{ $a := slice 1 2 3 }}
{{ $b := slice 2 3 4 }}
{{ $diff := collections.SymDiff $a $b }} Try / catch
{{ with try (collections.SymDiff $a $b) }}
{{ with .Err }}{{ errorf "symdiff: %s" . }}{{ else }}{{ .Value }}{{ end }}
{{ end }} Prevention
- Use slices of homogeneous, hashable scalar types (strings, numbers) — mixed or complex element types can fail conversion
- Normalize elements (e.g. `string`-ify) before diffing when sources vary
- Test symdiff with data from all content sources that feed it
When it happens
Trigger: Calling `{{ $a | symdiff $b }}` where the two slices have incompatible element types — e.g. a `[]int` diffed against a slice of pages or structs, or mixed-type `[]any` slices whose leftover elements can't convert to the result's concrete element type.
Common situations: Diffing `.Pages` against a hand-built `slice` of strings or params; mixing values from `.Params` (which decode as varying concrete types) with typed collections; assuming symdiff works on heterogeneous data like union types.
Related errors
- unable to convert value of type %q to %q
- expected a slice, got %T
- arguments to symdiff must be slices or arrays
- errWrongArgStructure
- errKeyIsEmptyString
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/36aa43ffc4150ecb.json.
Report an issue: GitHub ↗.