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

  1. Rename or remove one of the conflicting members in the target type.
  2. Use [DataMember]/[YamlMember]-style attributes to give one member a distinct serialized name.
  3. Check inheritance: hide the base member properly or exclude it via [DoNotSerialize]/ignore attributes so it is not scanned twice.
  4. 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

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


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)