dotnet/wpf · error
' ' can only host a ' ' or a ' '. ' ' is an invalid…
Error message
'{0}' can only host a '{1}' or a '{2}'. '{3}' is an invalid container. What it means
MenuItem validates its item containers: only MenuItem and Separator are legal children, since menu item containers must be menu items or separators. When the container resolution path encounters a container of any other type, it throws InvalidOperationException naming the host type, the two allowed types, and the offending container's type.
Solutions
- Add only MenuItem or Separator children; convert other objects into MenuItems (set Header for text).
- When data-binding, supply ItemContainerStyle or an ItemContainerTemplate so each data item is wrapped in a MenuItem.
- Put arbitrary content inside MenuItem.Header instead of adding it as a direct child item.
- If you need specialized containers, derive them from MenuItem so the type check passes.
Example fix
// before: menuItem.Items.Add(new Button { Content = "Click" }); // throws // after: menuItem.Items.Add(new MenuItem { Header = "Click" }); Defensive patterns
Strategy: type-guard
Validate before calling
static bool IsValidMenuItemChild(object item) => item is MenuItem || item is Separator;
Type guard
bool IsMenuContainer(DependencyObject c) => c is MenuItem || c is Separator;
Try / catch
try { menuItem.Items.Add(child); } catch (InvalidOperationException ex) when (ex.Message.Contains("invalid container")) { menuItem.Items.Add(new MenuItem { Header = child.ToString() }); } Prevention
- Only add MenuItem or Separator objects to MenuItem.Items.
- When binding ItemsSource to plain data, always set ItemContainerStyle/ItemContainerTemplate mapping to MenuItem.
- Nest arbitrary UI inside MenuItem.Header, not as a direct item.
- Derive custom menu containers from MenuItem.
When it happens
Trigger: Adding a non-MenuItem/non-Separator object (raw string, Button, TextBlock, custom control) to MenuItem.Items; or data-binding ItemsSource without an ItemContainerStyle/ItemContainerTemplate so the generated container is not a MenuItem, causing the check 'itemContainer is MenuItem || itemContainer is Separator' to fail.
Common situations: Binding MenuItem.ItemsSource to plain view-model objects without a container mapping; placing Label/Button/TextBlock children directly inside a MenuItem in XAML; custom control templates that generate foreign containers.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ' ' can only host a ' ' or a ' '. ' ' is an invalid…
- A panel with IsItemsHost="true" is not nested in an…
- Cannot explicitly modify Children collection of Panel used…
- ElementNotEnabledException
- Microsoft.Windows.Controls.SR.Format(Microsoft.Windows.Contr…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9614bc4d63f3839d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs:2101
/// <summary> Create or identify the element used to display the given item. </summary>
protected override DependencyObject GetContainerForItemOverride()
{
object currentItem = _currentItem;
_currentItem = null;
if (UsesItemContainerTemplate)
{
DataTemplate itemContainerTemplate = ItemContainerTemplateSelector.SelectTemplate(currentItem, this);
if (itemContainerTemplate != null)
{
object itemContainer = itemContainerTemplate.LoadContent();
if (itemContainer is MenuItem || itemContainer is Separator)
{
return itemContainer as DependencyObject;
}
else
{
throw new InvalidOperationException(SR.Format(SR.InvalidItemContainer, this.GetType().Name, nameof(MenuItem), nameof(Separator), itemContainer));
}
}
}
return new MenuItem();
}
/// <summary>
/// Called when the parent of the Visual has changed.
/// </summary>
/// <param name="oldParent">Old parent or null if the Visual did not have a parent before.</param>
protected internal override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
UpdateRole();
// Windows OS bug:1988393; DevDiv bug:107459
// MenuItem template contains ItemsPresenter where Grid.IsSharedSizeScope="true" and need to inherits PrivateSharedSizeScopeProperty valueView on GitHub (pinned to 81131a70a4)