dotnet/maui · error · InvalidCastException
renderer must be a Page renderer.
Error message
renderer must be a Page renderer.
What it means
Thrown by the iOS TabbedRenderer.SetTabBarItem when the renderer's VirtualView is not a Page. The TabbedRenderer expects each tab's handler to render a Page-derived element (ContentPage, NavigationPage, etc.). If a non-Page visual element was added to the TabbedPage's Children or the handler was misconfigured, the cast `renderer.VirtualView as Page` returns null and InvalidCastException is thrown.
Source
Thrown at src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs:558
}
}
}
void UpdateCurrentPage()
{
if (Tabbed is TabbedPage tabbed)
{
var count = tabbed.InternalChildren.Count;
var index = (int)SelectedIndex;
tabbed.CurrentPage = index >= 0 && index < count ? tabbed.GetPageByIndex(index) : null;
}
}
async void SetTabBarItem(IPlatformViewHandler renderer)
{
var page = renderer.VirtualView as Page;
if (page == null)
throw new InvalidCastException($"{nameof(renderer)} must be a {nameof(Page)} renderer.");
var icons = await GetIcon(page);
var resizedImage = TabbedViewExtensions.AutoResizeTabBarImage(TraitCollection, icons?.Item1);
var resizedSelectedImage = TabbedViewExtensions.AutoResizeTabBarImage(TraitCollection, icons?.Item2);
SetTabBarItem(resizedImage, resizedSelectedImage);
resizedImage?.Dispose();
resizedSelectedImage?.Dispose();
void SetTabBarItem(UIImage image, UIImage selectedImage)
{
renderer.ViewController.TabBarItem = new UITabBarItem(page.Title, image, selectedImage)
{
Tag = Tabbed?.Children.IndexOf(page) ?? -1,
AccessibilityIdentifier = page.AutomationId
};
}
icons?.Item1?.Dispose();View on GitHub (pinned to f377ff1c5e)
Solutions
- Ensure every child added to TabbedPage.Children is a Page subclass (ContentPage, NavigationPage, etc.).
- If using ContentView as tab content, wrap it in a ContentPage first.
- Verify handler mappings if using custom element types — only Page-derived elements are valid tab children.
- Prefer the modern MAUI TabbedPage alternatives (Shell with tabs, or TabbedPage with proper Page children) over the legacy compatibility path.
- Inspect which tab index triggers the error to identify the problematic child.
Example fix
// before
var tabbedPage = new TabbedPage();
tabbedPage.Children.Add(new ContentView { Content = new Label { Text = "Tab1" } }); // not a Page!
// after
var tabbedPage = new TabbedPage();
tabbedPage.Children.Add(new ContentPage { Title = "Tab1", Content = new Label { Text = "Tab1" } }); Defensive patterns
Strategy: type-guard
Validate before calling
// Verify children are Page types before adding to TabbedPage
foreach (var child in tabbedPage.Children)
{
if (child is not Page)
throw new InvalidCastException($"TabbedPage child '{child}' must be a Page.");
} Type guard
public static bool IsValidTabChild(Element element)
=> element is Page; Prevention
- Only add Page subclasses to TabbedPage.Children.
- Wrap ContentView in ContentPage if needed for tab content.
- Consider modern alternatives (Shell tabs, TabbedPage with Page children) over legacy Cell/compatibility APIs.
When it happens
Trigger: At line 558: `var page = renderer.VirtualView as Page; if (page == null) throw new InvalidCastException`. SetTabBarItem is called to configure each tab's UITabBarItem (title, icon). Triggered when the handler associated with a tab index produces a VirtualView that is not a Page subclass. This can happen when: (1) a non-Page element (e.g., a Layout, ContentView directly) is added to TabbedPage.Children; (2) the handler mapping is misconfigured for a custom element type; (3) a handler returns the wrong VirtualView type.
Common situations: 1) Adding a ContentView or Layout directly to TabbedPage.Children instead of a ContentPage. 2) Custom handler registration that maps a non-Page type to the TabbedRenderer's tab slots. 3) TabbedPage is a legacy/compatibility API — migration from Xamarin.Forms where Children contained non-Page items that happened to work. 4) Programmatic creation of TabbedPage with incorrect child types.
Related errors
- Element must be a TabbedPage
- Element must be of type Frame.
- New element must be a CarouselPage
- view
- self
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/318df5a44278e004.
Report an issue: GitHub.