stride3d/stride · error · InvalidOperationException

Failed to get ObjectDescriptor for type

Error message

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}]

What it means

ObjectDescriptor.Initialize also registers each member's AlternativeNames (alias names accepted during deserialization). If an alternate name collides with an already-registered member name (or another alias), registration would be ambiguous and Initialize throws InvalidOperationException naming the type, member, colliding alternate name, and existing member.

Solutions

  1. Remove or rename the conflicting AlternativeName entry on the member.
  2. Ensure aliases are unique across all members of the type (including real member names).
  3. If the alias was meant to support old data migration, delete or rename the member now occupying that name.

Example fix

// before
member.AlternativeNames = ["Name", "Name"];
// after
member.AlternativeNames = ["Name", "LegacyName"];
Defensive patterns

Strategy: validation

Validate before calling

var all = new HashSet<string>(StringComparer.Ordinal);
foreach (var m in type.GetMembers().Where(m => m is FieldInfo or PropertyInfo))
{
    if (!all.Add(m.Name)) throw new InvalidOperationException($"Alias {m.Name} collides");
    foreach (var a in GetAlternativeNames(m))
        if (!all.Add(a)) throw new InvalidOperationException($"Alias {a} collides");
}

Try / catch

try { var desc = TypeDescriptorFactory.Default.FindDescriptor(type); }
catch (InvalidOperationException ex) when (ex.Message.Contains("AlternativeNames") || ex.Message.Contains("alternateName")) { log.LogError(ex, "Alias collision on {Type}", type); }

Prevention

When it happens

Trigger: A member declares AlternativeNames containing a string equal to another member's name, another member's alias, or its own sibling alias; raised while building the ObjectDescriptor for that type.

Common situations: Merging legacy serialized names after a rename (e.g. alias 'oldName' that matches a still-present property); mass renames where the old name was kept as a field; aliases auto-generated per naming convention colliding with actual member 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/819b50410eabd199. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs:166

        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);
                }
            }
        }
    }

    public bool Contains(string memberName)
    {
        return mapMembers?.ContainsKey(memberName) == true;
    }

    protected virtual List<IMemberDescriptor> PrepareMembers()
    {
        if (Type == typeof(Type))

View on GitHub (pinned to 96fad776d2)