stride3d/stride · error · InvalidOperationException
Incompatible serializer found for same type in different…
Error message
Incompatible serializer found for same type in different assemblies for {0} What it means
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.
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
Example fix
// before
// AssemblyA
[DataSerializerGenericMode(DataSerializerGenericMode.None)]
class VecSerializer : DataSerializer<MyVec> {}
// AssemblyB
[DataSerializerGenericMode(DataSerializerGenericMode.GenericArityAndArguments)]
class VecSerializer2 : DataSerializer<MyVec> {}
// after
// keep exactly one:
[DataSerializerGenericMode(DataSerializerGenericMode.None)]
class VecSerializer : DataSerializer<MyVec> {} Defensive patterns
Strategy: validation
Validate before calling
// Ensure only one serializer exists per data type across referenced assemblies:
var seen = new Dictionary<Type, Type>();
foreach (var asm in referencedAssemblies)
foreach (var s in asm.GetTypes().Where(t => typeof(DataSerializer).IsAssignableFrom(t) && !t.IsAbstract))
{
var dataType = GetSerializedType(s);
if (seen.TryGetValue(dataType, out var dup))
Console.WriteLine($"[conflict] {dup.Name} vs {s.Name} both serialize {dataType.Name}");
else seen[dataType] = s;
} Try / catch
try { RegisterSerializer(type); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Incompatible serializer found"))
{
logger.Warn($"Duplicate serializer for {type}: keeping existing registration");
} Prevention
- One DataSerializer per data type per project
- Keep DataSerializerGenericMode consistent across all serializer copies
- Avoid copy-pasting serializers into multiple assemblies
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Unsupported generic resolution.
- Serialization of nested types referencing parent's generic…
- Could not find serializer for generic dependent type
- Can't deduce data serializer type for generic types.
- Unable to find a serializer for
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/d55f208945ad7a98.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs:462
}
public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
{
// Check if declaring type is generics
var resolvedType = dataType.Resolve();
if (resolvedType?.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))
{
throw new NotSupportedException(string.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " +
"[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType));
}
var profileInfo = GetSerializableTypes(profile);
if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var currentValue))
{
// TODO: Doesn't work in some generic case
if (currentValue.Mode != serializableTypeInfo.Mode)
throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp()));
return;
}
// Check that we don't simply try to add the same serializer than Default profile (optimized)
if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var defaultValue))
{
if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)
{
// Already added in default profile, early exit
return;
}
}
profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo);
// Scan and add dependencies (stored in EnumerateGenericInstantiations() methods)
ScanSerializerDependencies(dataType, serializableTypeInfo);
}View on GitHub (pinned to 96fad776d2)