stride3d/stride · error · InvalidOperationException
Two different classes have the same DataContract Alias
Error message
Two different classes have the same DataContract Alias [${dataContractAliasEntry.Name}]: ${dataContractAliasEntry.Type} and ${DataContractAliasMapping[dataContractAliasEntry.Name]} What it means
DataSerializerFactory scans assemblies for [DataContract] types and builds a mapping from each DataContract Alias to its Type. Two different classes declared the same alias, so the mapping would be ambiguous; the factory throws InvalidOperationException instead of silently letting the last-registered type win.
Solutions
- Make each [DataContract("Alias")] alias unique across all registered assemblies
- If the duplicate is stale, delete or rename the old attribute before re-registering the assembly
- Regenerate the serializer assembly (Stride codegen) after fixing aliases, then re-run RegisterSerializationAssembly
- If a collision is intentional (same type moved assemblies), keep only one registration or unregister the old assembly first
Example fix
// before
// AssemblyA: [DataContract("MyData")] class MyData { }
// AssemblyB: [DataContract("MyData")] class MyDataVariant { }
// after
// AssemblyB: [DataContract("MyDataVariant")] class MyDataVariant { } Defensive patterns
Strategy: validation
Validate before calling
// scan registered assemblies for duplicate DataContract aliases before registering
var aliasGroups = assemblies
.SelectMany(a => a.GetTypes().Where(t => t.GetCustomAttributes<DataContractAliasAttribute>().Any()))
.SelectMany(t => t.GetCustomAttributes<DataContractAliasAttribute>().Select(attr => (attr.Name, Type: t)));
var dupes = aliasGroups.GroupBy(x => x.Name).Where(g => g.Select(x => x.Type).Distinct().Count() > 1).ToList();
if (dupes.Any()) throw new InvalidOperationException("Duplicate aliases: " + string.Join(",", dupes.Select(d => d.Key))); Try / catch
try
{
Serialization.RegisterSerializationAssembly(assembly);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DataContract Alias"))
{
logger.Fatal(ex, "DataContract alias collision - fix the [DataContract] aliases listed above");
throw;
} Prevention
- Keep DataContract aliases globally unique; prefix them with your module name
- After renaming a class, update its alias rather than leaving a stale duplicate
- Regenerate serializer assemblies after any DataContract attribute change
- Only register each assembly once (unregister before re-registering)
When it happens
Trigger: Registering two assemblies (RegisterSerializers, via RegisterSerializationAssembly/UnregisterSerializationAssembly) that each contain a [DataContract("SameAlias")] on different types; adding a DataContract alias that duplicates one in a referenced module; stale serializer assembly generated from an older alias still being loaded.
Common situations: Renaming a class but leaving its old DataContract alias in place while a new class takes the same alias; two plugins shipping identically-named custom data-contract types; copy-pasting a component class (including its DataContract attribute) into another assembly without changing the alias; assembly regeneration/registration ordering after a version upgrade.
Related errors
- No serializer available for type
- No serializer available for type id
- Could not find serializer for type
- Can't find a type with alias
- Custom strides is not supported with packed PixelFormats
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6c0cbd357cad115e.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Serialization/DataSerializerFactory.cs:243
{
AvailableAssemblySerializers.TryGetValue(assembly, out var assemblySerializers);
return assemblySerializers;
}
}
private static void RegisterSerializers(AssemblySerializers assemblySerializers)
{
// Register data contract aliases
foreach (var dataContractAliasEntry in assemblySerializers.DataContractAliases)
{
try
{
// TODO: Warning, exception or override if collision? (currently exception)
DataContractAliasMapping.Add(dataContractAliasEntry.Name, dataContractAliasEntry.Type);
}
catch (Exception)
{
throw new InvalidOperationException($"Two different classes have the same DataContract Alias [{dataContractAliasEntry.Name}]: {dataContractAliasEntry.Type} and {DataContractAliasMapping[dataContractAliasEntry.Name]}");
}
}
// Register serializers
foreach (var assemblySerializerPerProfile in assemblySerializers.Profiles)
{
var profile = assemblySerializerPerProfile.Key;
if (!DataSerializersPerProfile.TryGetValue(profile, out var dataSerializers))
{
dataSerializers = new Dictionary<Type, AssemblySerializerEntry>();
DataSerializersPerProfile.Add(profile, dataSerializers);
}
foreach (var assemblySerializer in assemblySerializerPerProfile.Value)
{
dataSerializers.TryAdd(assemblySerializer.ObjectType, assemblySerializer);
}View on GitHub (pinned to 96fad776d2)