{"record":{"id":"d55f208945ad7a98","repo":"stride3d/stride","slug":"incompatible-serializer-found-for-same-type-in-different","errorCode":null,"errorMessage":"Incompatible serializer found for same type in different assemblies for {0}","messagePattern":"Incompatible serializer found for same type in different assemblies for (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs","lineNumber":462,"sourceCode":"    }\n\n    public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = \"Default\")\n    {\n        // Check if declaring type is generics\n        var resolvedType = dataType.Resolve();\n        if (resolvedType?.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))\n        {\n            throw new NotSupportedException(string.Format(\"Serialization of nested types referencing parent's generic parameters is not currently supported. \" +\n                                                          \"[Nested type={0} Parent={1}]\", resolvedType.FullName, resolvedType.DeclaringType));\n        }\n\n        var profileInfo = GetSerializableTypes(profile);\n\n        if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var currentValue))\n        {\n            // TODO: Doesn't work in some generic case\n            if (currentValue.Mode != serializableTypeInfo.Mode)\n                throw new InvalidOperationException(string.Format(\"Incompatible serializer found for same type in different assemblies for {0}\", dataType.ConvertCSharp()));\n            return;\n        }\n\n        // Check that we don't simply try to add the same serializer than Default profile (optimized)\n        if (profile != \"Default\" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var defaultValue))\n        {\n            if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)\n            {\n                // Already added in default profile, early exit\n                return;\n            }\n        }\n\n        profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo);\n\n        // Scan and add dependencies (stored in EnumerateGenericInstantiations() methods)\n        ScanSerializerDependencies(dataType, serializableTypeInfo);\n    }","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs#L444-L480","documentation":"AddSerializableType throws when the same data type already has a registered serializer with a different DataSerializerGenericMode, meaning two assemblies contributed incompatible serializers for the same type. The processor cannot pick one mode, so registration fails.","triggerScenarios":"Two assemblies register serializers for the same dataType with different generic modes (currentValue.Mode != serializableTypeInfo.Mode), e.g. one [DataSerializer] without generic mode and another with GenericArityAndArguments.","commonSituations":"Referencing two plugin/game assemblies that each define a serializer for a shared type; a package upgrade introduces a duplicate serializer; partial copy-paste of a serializer into a second assembly.","solutions":["Remove or de-duplicate the conflicting DataSerializer so only one remains for that type","Align the DataSerializerGenericMode on both serializer declarations","Exclude one of the assemblies from the assembly processor","If in Stride source, resolve the TODO for the generic case in AddSerializableType"],"exampleFix":"// before\n// AssemblyA\n[DataSerializerGenericMode(DataSerializerGenericMode.None)]\nclass VecSerializer : DataSerializer<MyVec> {}\n// AssemblyB\n[DataSerializerGenericMode(DataSerializerGenericMode.GenericArityAndArguments)]\nclass VecSerializer2 : DataSerializer<MyVec> {}\n// after\n// keep exactly one:\n[DataSerializerGenericMode(DataSerializerGenericMode.None)]\nclass VecSerializer : DataSerializer<MyVec> {}","handlingStrategy":"validation","validationCode":"// Ensure only one serializer exists per data type across referenced assemblies:\nvar seen = new Dictionary<Type, Type>();\nforeach (var asm in referencedAssemblies)\n    foreach (var s in asm.GetTypes().Where(t => typeof(DataSerializer).IsAssignableFrom(t) && !t.IsAbstract))\n    {\n        var dataType = GetSerializedType(s);\n        if (seen.TryGetValue(dataType, out var dup))\n            Console.WriteLine($\"[conflict] {dup.Name} vs {s.Name} both serialize {dataType.Name}\");\n        else seen[dataType] = s;\n    }","typeGuard":null,"tryCatchPattern":"try { RegisterSerializer(type); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Incompatible serializer found\"))\n{\n    logger.Warn($\"Duplicate serializer for {type}: keeping existing registration\");\n}","preventionTips":["One DataSerializer per data type per project","Keep DataSerializerGenericMode consistent across all serializer copies","Avoid copy-pasting serializers into multiple assemblies"],"tags":["serialization","conflict","assemblies","generics"],"backgroundTag":"conflicting-config-options","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}