dotnet/maui · error · ArgumentException

{nameof(element)} must be of type {nameof(Button)}

Error message

{nameof(element)} must be of type {nameof(Button)}

What it means

The fast ButtonRenderer's explicit SetElement requires a Button. It null-checks then verifies `element is Button` before casting. The fast-renderer family (Button, Label, Image, Frame) each enforce their concrete type because they are not generic.

Source

Thrown at src/Compatibility/Core/src/Android/FastRenderers/ButtonRenderer.cs:114

			var result = _buttonLayoutManager.GetDesiredSize(widthConstraint, heightConstraint);

			if (setHint)
				Control.Hint = hint;

			return result;
		}

		void IVisualElementRenderer.SetElement(VisualElement element)
		{
			if (element == null)
			{
				throw new ArgumentNullException(nameof(element));
			}

			if (!(element is Button))
			{
				throw new ArgumentException($"{nameof(element)} must be of type {nameof(Button)}");
			}

			VisualElement oldElement = Button;
			Button = (Button)element;

			Performance.Start(out string reference);

			OnElementChanged(new ElementChangedEventArgs<Button>(oldElement as Button, Button));

			SendVisualElementInitialized(element, this);

			Performance.Stop(reference);
		}

		void IVisualElementRenderer.SetLabelFor(int? id)
		{
			if (_defaultLabelFor == null)
			{

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Ensure ExportRenderer(typeof(Button), typeof(ButtonRenderer)) (or your subclass) is correctly typed.
  2. Do not pass non-Button elements when reusing or manually driving the renderer.
  3. If subclassing for a control that extends Button, the check still passes; otherwise pick the right base renderer.

Example fix

// before
[assembly: ExportRenderer(typeof(Label), typeof(MyButtonRenderer))]
// after
[assembly: ExportRenderer(typeof(Button), typeof(MyButtonRenderer))]
Defensive patterns

Strategy: type-guard

Validate before calling

if (element is null) throw new ArgumentNullException(nameof(element));
if (element is not Button) throw new ArgumentException("Expected Button.", nameof(element));
((IVisualElementRenderer)renderer).SetElement(element);

Type guard

static bool IsButton(VisualElement e) => e is Button;

Prevention

When it happens

Trigger: SetElement called with a VisualElement that is not a Button — almost always a wrong ExportRenderer registration or a manual renderer call in custom handler code.

Common situations: A custom subclass of ButtonRenderer registered for a non-Button control, or a handler migration where the old fast-renderer attribute points at the wrong control type.

Related errors


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