{"record":{"id":"13cffb8231449073","repo":"gohugoio/hugo","slug":"s-is-not-assignable-to-s","errorCode":null,"errorMessage":"%s is not assignable to %s","messagePattern":"(.+?) is not assignable to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/reflect_helpers.go","lineNumber":92,"sourceCode":"\t\t}\n\t}\n\n\treturn seen, nil\n}\n\n// We have some different numeric and string types that we try to behave like\n// they were the same.\nfunc convertValue(v reflect.Value, to reflect.Type) (reflect.Value, error) {\n\tif v.Type().AssignableTo(to) {\n\t\treturn v, nil\n\t}\n\tswitch kind := to.Kind(); {\n\tcase kind == reflect.String:\n\t\treturn hreflect.ToStringValueE(v)\n\tcase hreflect.IsNumber(kind):\n\t\treturn convertNumber(v, to)\n\tdefault:\n\t\treturn reflect.Value{}, fmt.Errorf(\"%s is not assignable to %s\", v.Type(), to)\n\t}\n}\n\nfunc convertNumber(v reflect.Value, typ reflect.Type) (reflect.Value, error) {\n\tif v, ok := hreflect.ConvertIfPossible(v, typ); ok {\n\t\treturn v, nil\n\t}\n\treturn reflect.Value{}, fmt.Errorf(\"unable to convert value of type %q to %q\", v.Type().String(), typ.String())\n}\n\nfunc newSliceElement(items any) any {\n\ttp := reflect.TypeOf(items)\n\tif tp == nil {\n\t\treturn nil\n\t}\n\tswitch tp.Kind() {\n\tcase reflect.Array, reflect.Slice:\n\t\ttp = tp.Elem()","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/collections/reflect_helpers.go#L74-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{{ symdiff $structSlice $intSlice }}\n// after\n{{ symdiff $intSliceA $intSliceB }}","handlingStrategy":"type-guard","validationCode":"func elementTypesCompatible(a, b reflect.Type) bool {\n    if a == b { return true }\n    if a.Kind() == reflect.String || b.Kind() == reflect.String { return true }\n    if hreflect.IsNumber(a.Kind()) && hreflect.IsNumber(b.Kind()) { return true }\n    return a.Kind() == reflect.Interface || b.Kind() == reflect.Interface\n}","typeGuard":"func isConvertibleType(t reflect.Type) bool {\n    return t.Kind() == reflect.String || hreflect.IsNumber(t.Kind())\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["go","hugo","template","collections","type-mismatch","conversion"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}