stride3d/stride · error · InvalidOperationException
The control corresponding to the given parentId is a…
Error message
The control corresponding to the given parentId is a ContentControl that already has a Content.
What it means
UIEditorController.AddPart throws this InvalidOperationException when the target parent is a ContentControl that already has Content. A ContentControl holds exactly one child; assigning a second would silently overwrite existing game-side content, so the controller refuses the add.
Solutions
- Remove or move the existing content of the ContentControl before adding the new part.
- Use a Panel-based parent (StackPanel, Grid) that accepts multiple children.
- Check the parent's content (ContentControl.Content != null) before calling AddPart.
- If replacement is intended, update the existing content node instead of adding a new part.
Example fix
// before
controller.AddPart(newPart, contentControlId); // throws if content exists
// after
var parent = FindViewModel(contentControlId) as ContentControlViewModel;
if (parent?.Content == null)
controller.AddPart(newPart, contentControlId);
else
controller.AddPart(newPart, panelParentId);
Defensive patterns
Strategy: type-guard
Validate before calling
var parentVm = FindViewModel(parentId) as ContentControlViewModel; bool canAdd = parentVm != null && parentVm.Content == null;
Type guard
bool CanHostContent(UIElementViewModel parent) => parent is ContentControlViewModel cc && cc.Content == null;
Try / catch
try { controller.AddPart(newPart, parentId); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already has a Content")) {
// pick a panel parent or clear the existing content first
} Prevention
- Check ContentControl content occupancy before adding children.
- Prefer Panel parents for multiple children.
- Avoid duplicate add calls against single-slot containers.
- Centralize parent selection logic to respect container capacity.
When it happens
Trigger: Adding a part whose parentId refers to a ContentControl that already contains a child; calling AddPart twice with the same single-child parent; dragging multiple elements into a single-slot container.
Common situations: Duplicating elements into a button/content host that already has content, replaying scripts against an already-populated layout, drag-drop of several items onto one ContentControl.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The given parentId does not correspond to any existing part.
- The given assetSidePart.Id does not correspond to any…
- The given element is not a child of this panel.
- Changing the panel from a user library type is currently…
- Grouping elements into a user library type isn't supported.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/58401c1083d65c43.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/UIEditor/Services/UIEditorController.cs:237
RootElements[assetSidePart.Id] = gameSidePart;
}
else
{
var parentElement = (UIElement)FindPart(parentId.Value);
if (parentElement == null)
throw new InvalidOperationException($"The given {nameof(parentId)} does not correspond to any existing part.");
var panel = parentElement as Panel;
var contentControl = parentElement as ContentControl;
if (panel != null)
{
GameSideNodeContainer.GetNode(panel.Children).Add(gameSidePart);
}
else if (contentControl != null)
{
if (contentControl.Content != null)
{
throw new InvalidOperationException($"The control corresponding to the given {nameof(parentId)} is a ContentControl that already has a Content.");
}
GameSideNodeContainer.GetNode(contentControl)[nameof(contentControl.Content)].Update(gameSidePart);
}
}
});
}
/// <inheritdoc />
public override Task RemovePart([NotNull] UIHierarchyItemViewModel parent, UIElement assetSidePart)
{
EnsureAssetAccess();
return InvokeAsync(() =>
{
Logger.Debug($"Removing element {assetSidePart.Id} from game-side scene");
var partId = new AbsoluteId(AssetId.Empty, assetSidePart.Id);
var part = (UIElement)FindPart(partId);
if (part == null)View on GitHub (pinned to 96fad776d2)