dotnet/maui · error · ArgumentException

Element must be of type Frame.

Error message

Element must be of type Frame.

What it means

MaterialFrameRenderer renders Material Design Frame elements on Android. SetElement casts the VisualElement to Frame and throws ArgumentException on mismatch. The renderer applies Material card-scheme corner radius and elevation logic specific to Frame, so an incompatible element cannot be processed.

Source

Thrown at src/Compatibility/Material/src/Android/MaterialFrameRenderer.cs:283

				if (_defaultBackgroundDrawable == null)
					_defaultBackgroundDrawable = Background;

				_backgroundGradientDrawable = new GradientDrawable();
				_backgroundGradientDrawable.SetShape(ShapeType.Rectangle);

				_backgroundGradientDrawable.SetCornerRadius(Radius);
				_backgroundGradientDrawable.UpdateBackground(bgBrush, Height, Width);

				Background = _backgroundGradientDrawable;
			}
		}

		// IVisualElementRenderer
		VisualElement IVisualElementRenderer.Element => Element;
		VisualElementTracker IVisualElementRenderer.Tracker => _visualElementTracker;
		AView IVisualElementRenderer.View => this;
		void IVisualElementRenderer.SetElement(VisualElement element) =>
			Element = (element as Frame) ?? throw new ArgumentException("Element must be of type Frame.");
		void IVisualElementRenderer.UpdateLayout() =>
			_visualElementTracker?.UpdateLayout();

		SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
		{
			var context = Context;
			return new SizeRequest(new Size(context.ToPixels(20), context.ToPixels(20)));
		}

		void IVisualElementRenderer.SetLabelFor(int? id)
		{
			if (_defaultLabelFor == null)
				_defaultLabelFor = ViewCompat.GetLabelFor(this);

			ViewCompat.SetLabelFor(this, (int)(id ?? _defaultLabelFor));
		}

		// IEffectControlProvider

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Confirm the ExportRenderer attribute maps Frame to MaterialFrameRenderer.
  2. If migrating from Frame to Border/ContentView, update both the element type and the renderer accordingly.
  3. Ensure no custom element type without a Frame base is registered against this renderer.
  4. Check for conflicting registrations across multiple assemblies.

Example fix

// before
[assembly: ExportRenderer(typeof(ContentView), typeof(MaterialFrameRenderer))]

// after
[assembly: ExportRenderer(typeof(Frame), typeof(MaterialFrameRenderer))]
Defensive patterns

Strategy: type-guard

Validate before calling

if (element is not Frame)
    throw new InvalidOperationException($"Expected Frame, got {element?.GetType().Name}");
renderer.SetElement(element);

Type guard

static bool IsFrame(VisualElement? element) => element is Frame;

Prevention

When it happens

Trigger: The handler dispatch sends a non-Frame element to MaterialFrameRenderer. Happens with incorrect ExportRenderer registrations or when migrating a custom ContentView to be rendered by the Frame renderer.

Common situations: Confusing Frame with ContentView or Border in renderer registrations. MAUI migration where Frame was replaced by Border but the renderer mapping was not updated. Custom layouts accidentally mapped to the Frame renderer.

Related errors


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