gohugoio/hugo · error
symdiff: failed to convert value
Error message
symdiff: failed to convert value: %w
What it means
Wrapping error from SymDiff when convertValue fails while converting an element to the result slice's element type. The %w verb wraps the underlying convertValue error (which may itself be the 'is not assignable' or 'unable to convert' message). This is the user-facing surface for element-coercion failures during symmetric difference computation.
Solutions
- Read the wrapped error to find the exact conversion failure (assignable vs numeric).
- Normalize both slices to the same element type before calling symdiff.
- Map elements to strings or numbers upstream.
- Verify element types match across all data sources.
Example fix
// before
{{ symdiff $stringSlice $intSlice }}
// after
{{ symdiff $stringSliceA $stringSliceB }} Defensive patterns
Strategy: try-catch
Validate before calling
func symdiffSafe(a, b any) (any, error) {
ta := reflect.TypeOf(a); tb := reflect.TypeOf(b)
if ta == nil || tb == nil { return nil, errors.New("nil operand") }
if ta.Kind() != reflect.Slice && ta.Kind() != reflect.Array { return nil, fmt.Errorf("a must be slice/array") }
if tb.Kind() != reflect.Slice && tb.Kind() != reflect.Array { return nil, fmt.Errorf("b must be slice/array") }
if ta.Elem() != tb.Elem() && !elementTypesCompatible(ta.Elem(), tb.Elem()) {
return nil, fmt.Errorf("element types incompatible: %s vs %s", ta.Elem(), tb.Elem())
}
return ns.SymDiff(a, b)
} Type guard
func symdiffCompatible(a, b any) bool {
ta, tb := reflect.TypeOf(a), reflect.TypeOf(b)
if ta == nil || tb == nil { return false }
if ta.Kind() != reflect.Slice && ta.Kind() != reflect.Array { return false }
if tb.Kind() != reflect.Slice && tb.Kind() != reflect.Array { return false }
return ta.Elem() == tb.Elem() || elementTypesCompatible(ta.Elem(), tb.Elem())
} Try / catch
r, err := ns.SymDiff(s2, s1)
if err != nil {
// err wraps the conversion failure; unwrap for the root cause
return nil, fmt.Errorf("symdiff failed: %w", err)
} Prevention
- Normalize both slices to the same element type before symdiff.
- Read the wrapped error to find the exact conversion failure.
- Map elements to strings or numbers upstream.
- Verify element type compatibility across all data sources.
When it happens
Trigger: Calling `{{ symdiff $a $b }}` where elements of $a and $b cannot be coerced to a common type — e.g. []string vs []int, or slices of incompatible structs. convertValue returns an error inside the SymDiff loop and it is wrapped here.
Common situations: Author assumes two slices are element-compatible when they are not, or data sources produce differently-typed slices (JSON numbers vs strings). Common when one slice comes from front matter and another from a data file.
Related errors
- arguments to symdiff must be slices or arrays
- index of type %T with args
- is not assignable to
- unable to convert value of type
- arguments must be slices or arrays
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/36aa43ffc4150ecb.
Report an issue: GitHub.
Appendix: 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 52c9bd7908)