stride3d/stride · error · InvalidOperationException
Failed to get ObjectDescriptor for type
Error message
Failed to get ObjectDescriptor for type [{0}]. The member [{1}] cannot be registered as a member with the same name is already registered [{2}] What it means
During ObjectDescriptor.Initialize, members are registered by name into mapMembers; if two members resolve to the same serialized name (after naming-convention processing), the descriptor cannot disambiguate them and throws InvalidOperationException. This is an internal invariant: a type where two distinct members produce identical keys would make serialization ambiguous.
Solutions
- Rename or remove one of the conflicting members in the target type.
- Use [DataMember]/[YamlMember]-style attributes to give one member a distinct serialized name.
- Check inheritance: hide the base member properly or exclude it via [DoNotSerialize]/ignore attributes so it is not scanned twice.
- Fix the naming convention so it does not collapse distinct member names to the same key.
Example fix
// before
public class Data
{
public int Value;
public int Value { get; set; }
}
// after
public class Data
{
public int Value { get; set; }
} Defensive patterns
Strategy: validation
Validate before calling
var names = type.GetMembers()
.Where(m => m is FieldInfo or PropertyInfo)
.Select(m => NamingHelper.Convert(m.Name, convention))
.GroupBy(n => n, StringComparer.Ordinal)
.Where(g => g.Count() > 1).ToList();
if (names.Count > 0) throw new InvalidOperationException($"Duplicate member names: {string.Join(", ", names)}"); Try / catch
try { var desc = TypeDescriptorFactory.Default.FindDescriptor(type); }
catch (InvalidOperationException ex) when (ex.Message.Contains("cannot be registered as a member")) { log.LogError(ex, "Type {Type} has duplicate member names", type); } Prevention
- Avoid field/property pairs with the same name in serialized types.
- Do not shadow base-class members with 'new' in serializable types.
- Check that naming conventions don't collapse distinct member names.
- Run descriptor construction over all serializable types in CI.
When it happens
Trigger: Constructing an ObjectDescriptor (directly or via TypeDescriptorFactory) for a type containing two members with identical names after convention processing — e.g. duplicate property/field names, a field and property with the same name, or shadowed members from inheritance both returned by GetMembers.
Common situations: Types using unusual naming conventions (camelCase/snake_case conversions collapsing 'FooBar' and 'foo_bar' style pairs); shadowing members with the 'new' keyword in derived classes; generated/DTO code with duplicate names.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Failed to get ObjectDescriptor for type
- The type of collection does not have a parameterless…
- The type of dictionary does not have a parameterless…
- The order of the Asset.Id property must be lower than the…
- Event handlers can't be added or removed after the…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6efed05a1652bb98.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs:154
if (keyComparer != null)
{
memberList.Sort(keyComparer);
}
// Free the member list
members = [.. memberList];
// If no members found, we don't need to build a dictionary map
if (members.Length == 0)
return;
mapMembers = new Dictionary<string, IMemberDescriptor>(members.Length);
foreach (var member in members)
{
if (mapMembers.TryGetValue(member.Name, out var existingMember))
{
throw new InvalidOperationException("Failed to get ObjectDescriptor for type [{0}]. The member [{1}] cannot be registered as a member with the same name is already registered [{2}]".ToFormat(Type.FullName, member, existingMember));
}
mapMembers.Add(member.Name, member);
// If there is any alternative names, register them
if (member.AlternativeNames != null)
{
foreach (var alternateName in member.AlternativeNames)
{
if (mapMembers.TryGetValue(alternateName, out existingMember))
{
throw new InvalidOperationException($"Failed to get ObjectDescriptor for type [{Type.FullName}]. The member [{member}] cannot be registered as a member with the same name [{alternateName}] is already registered [{existingMember}]");
}
remapMembers ??= [];
mapMembers[alternateName] = member;
remapMembers.Add(alternateName);
}View on GitHub (pinned to 96fad776d2)