gohugoio/hugo · error
%s is not assignable to %s
Error message
%s is not assignable to %s
What it means
Thrown by convertValue when a value cannot be assigned to the target type and the target kind is neither string nor numeric (so neither ToStringValueE nor convertNumber applies). convertValue is used by set operations (e.g. SymDiff) to coerce elements to the result slice's element type. Both the source type and target type are named via %s.
Source
Thrown at tpl/collections/reflect_helpers.go:92
}
}
return seen, nil
}
// We have some different numeric and string types that we try to behave like
// they were the same.
func convertValue(v reflect.Value, to reflect.Type) (reflect.Value, error) {
if v.Type().AssignableTo(to) {
return v, nil
}
switch kind := to.Kind(); {
case kind == reflect.String:
return hreflect.ToStringValueE(v)
case hreflect.IsNumber(kind):
return convertNumber(v, to)
default:
return reflect.Value{}, fmt.Errorf("%s is not assignable to %s", v.Type(), to)
}
}
func convertNumber(v reflect.Value, typ reflect.Type) (reflect.Value, error) {
if v, ok := hreflect.ConvertIfPossible(v, typ); ok {
return v, nil
}
return reflect.Value{}, fmt.Errorf("unable to convert value of type %q to %q", v.Type().String(), typ.String())
}
func newSliceElement(items any) any {
tp := reflect.TypeOf(items)
if tp == nil {
return nil
}
switch tp.Kind() {
case reflect.Array, reflect.Slice:
tp = tp.Elem()View on GitHub (pinned to 52c9bd7908)
Solutions
- Ensure both slices share a compatible element type before calling SymDiff.
- Map/transform elements to a common type (string or number) upstream.
- Avoid symdiff on slices of custom structs unless their types match.
- Inspect both types named in the error to find the incompatibility.
Example fix
// before
{{ symdiff $structSlice $intSlice }}
// after
{{ symdiff $intSliceA $intSliceB }} Defensive patterns
Strategy: type-guard
Validate before calling
func elementTypesCompatible(a, b reflect.Type) bool {
if a == b { return true }
if a.Kind() == reflect.String || b.Kind() == reflect.String { return true }
if hreflect.IsNumber(a.Kind()) && hreflect.IsNumber(b.Kind()) { return true }
return a.Kind() == reflect.Interface || b.Kind() == reflect.Interface
} Type guard
func isConvertibleType(t reflect.Type) bool {
return t.Kind() == reflect.String || hreflect.IsNumber(t.Kind())
} Prevention
- Ensure both set-operation slices share a compatible element type.
- Map heterogeneous elements to strings or numbers upstream.
- Avoid symdiff on slices of custom structs unless types match exactly.
- Inspect both types in the error to locate the incompatibility.
When it happens
Trigger: SymDiff (or another caller of convertValue) where the two input slices have element types that cannot be reconciled — e.g. symdiff a []struct against []int where the struct isn't string/number-coercible. The default branch of convertValue fires for non-string, non-number target kinds.
Common situations: Mixing slices of incompatible element types in set operations, or evolving a slice's element type during a refactor while old data remains. Less common than the slice/array type errors but arises with heterogeneous structs.
Related errors
- incompatible map types, got %T to %T
- unable to convert value of type %q to %q
- symdiff: failed to convert value: %w
- argument must be a slice
- union does not support slices or arrays of uncomparable type
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/13cffb8231449073.
Report an issue: GitHub.