AvaloniaUI/Avalonia · error · InvalidOperationException

Expected control '{name}' to be '{typeof(T)} but it was '{re

Error message

Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.

What it means

Thrown by NameScopeExtensions.Find<T>(INameScope, string) when a control with the requested name exists in the scope but is not assignable to the requested generic type T. Find<T> returns null when nothing is found, but treats a type mismatch as a programming error.

Source

Thrown at src/Avalonia.Base/Controls/NameScopeExtensions.cs:38

        public static T? Find<T>(this INameScope nameScope, string name)
            where T : class
        {
            _ = nameScope ?? throw new ArgumentNullException(nameof(nameScope));
            _ = name ?? throw new ArgumentNullException(nameof(name));

            var result = nameScope.Find(name);

            if (result == null)
            {
                return null;
            }

            if (result is T typed)
            {
                return typed;
            }

            throw new InvalidOperationException(
                $"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
        }

        /// <summary>
        /// Finds a named element in an <see cref="INameScope"/>.
        /// </summary>
        /// <typeparam name="T">The element type.</typeparam>
        /// <param name="anchor">The control to take the name scope from.</param>
        /// <param name="name">The name.</param>
        /// <returns>The named element or null if not found.</returns>
        public static T? Find<T>(this ILogical anchor, string name)
            where T : class
        {
            _ = anchor ?? throw new ArgumentNullException(nameof(anchor));
            _ = name ?? throw new ArgumentNullException(nameof(name));
            var styledAnchor = anchor as StyledElement;
            if (styledAnchor == null)
                return null;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Align the generic type parameter with the actual registered control type in XAML.
  2. If you are unsure of the type, use the non-generic Find(name) and check/cast manually.
  3. If the control type genuinely varies, use Find<object> or Find<IControl> and narrow at runtime.

Example fix

// before
var box = nameScope.Find<TextBox>("myLabel"); // throws, it's a Label
// after
var label = nameScope.Find<Label>("myLabel");
Defensive patterns

Strategy: type-guard

Validate before calling

var found = nameScope.Find(name);
if (found is T typed) return typed;
return null; // or handle the type mismatch explicitly

Type guard

static T? SafeFind<T>(INameScope scope, string name) where T : class
{
    var found = scope.Find(name);
    return found as T; // null if wrong type, no throw
}

Try / catch

try { return nameScope.Find<T>(name); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Expected control"))
{ return null; }

Prevention

When it happens

Trigger: Calling nameScope.Find<TextBox>("myButton") where "myButton" is registered as a Button. The name resolves but result is T fails.

Common situations: XAML x:Name was changed to a different control type but the C# Find<T> call was not updated. Refactoring a view swapped a control type (e.g., TextBlock to Label) while Find<T> still requests the old type. Generic type inference picks the wrong T.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/97b73b0f8138a9a2. Report an issue: GitHub.