dotnet/maui · error · ArgumentException

element is not of type " + typeof(TElement)

Error message

element is not of type " + typeof(TElement)

What it means

VisualElementRenderer<TElement> is the generic base for the (legacy/shell) Android renderer pipeline. Its explicit SetElement checks `element is TElement` and throws ArgumentException if false, then delegates to the protected SetElement(TElement). TElement is the concrete control type the renderer was built for.

Source

Thrown at src/Compatibility/Core/src/Android/VisualElementRenderer.cs:116

		VisualElement IVisualElementRenderer.Element => Element;

		event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
		{
			add { _elementChangedHandlers.Add(value); }
			remove { _elementChangedHandlers.Remove(value); }
		}

		public virtual SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
		{
			Measure(widthConstraint, heightConstraint);
			return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), MinimumSize());
		}

		void IVisualElementRenderer.SetElement(VisualElement element)
		{
			if (!(element is TElement))
				throw new ArgumentException("element is not of type " + typeof(TElement), nameof(element));

			SetElement((TElement)element);
		}

		public VisualElementTracker Tracker { get; private set; }

		public void UpdateLayout()
		{
			Performance.Start(out string reference);
			Tracker?.UpdateLayout();
			Performance.Stop(reference);
		}

		AView IVisualElementRenderer.View => this;

		public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
		public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Match ExportRenderer(typeof(TElement), typeof(VisualElementRenderer<TElement> subclass)) so the element type aligns with TElement.
  2. When subclassing, set TElement to the exact control type the renderer handles.
  3. Avoid invoking SetElement directly with elements of a different type.

Example fix

// before
[assembly: ExportRenderer(typeof(ScrollView), typeof(MyEntryRenderer))]
// after — TElement aligns with the registered control
[assembly: ExportRenderer(typeof(Entry), typeof(MyEntryRenderer))] // where MyEntryRenderer : VisualElementRenderer<Entry>
Defensive patterns

Strategy: type-guard

Validate before calling

static void Attach<TElement>(VisualElementRenderer<TElement> r, VisualElement e) where TElement : VisualElement
{
    if (e is null) throw new ArgumentNullException(nameof(e));
    if (e is not TElement typed)
        throw new ArgumentException($"Expected {typeof(TElement).Name}, got {e.GetType().Name}.", nameof(e));
    ((IVisualElementRenderer)r).SetElement(typed);
}

Type guard

static bool MatchesRenderer<TElement>(VisualElement e) where TElement : VisualElement => e is TElement;

Prevention

When it happens

Trigger: SetElement called with an element whose runtime type is not assignable to the renderer's TElement generic parameter. Typical of an incorrect ExportRenderer registration or a manual call.

Common situations: ExportRenderer pairs a renderer generic with a mismatched control; a custom renderer subclass changes TElement but the attribute still names the old control; handler/router dispatches the wrong renderer type.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/b9ca0e6f73488337. Report an issue: GitHub.