stride3d/stride · error · InvalidOperationException
A category cannot be deleted
Error message
A category cannot be deleted
What it means
CategoryViewModel represents an organizational category node in the asset tree, not a deletable entity. Its UpdateIsDeletedStatus override throws InvalidOperationException if something marks it as deleted. This is an internal invariant: only leaf items can be deleted, categories are structural nodes.
Solutions
- Filter selection to deletable item view models before deleting; skip nodes whose IsEditable/CanDelete indicates a category.
- Handle CanDelete returning false instead of forcing delete on category nodes.
- Call delete operations only on concrete asset/directory view models, not on CategoryViewModel instances.
Example fix
// before foreach (var node in selectedNodes) node.Delete(); // after foreach (var node in selectedNodes.OfType<AssetViewModel>()) node.Delete();
Defensive patterns
Strategy: validation
Validate before calling
if (node is CategoryViewModel) { logger.Info("Categories cannot be deleted"); return; } Type guard
bool IsDeletableNode(object node) => node is not CategoryViewModel;
Try / catch
try { node.Delete(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("category")) { logger.Warn("Cannot delete a category node; delete its items instead"); } Prevention
- Filter tree selections to item view models before delete operations
- Respect CanDelete(out error) results instead of forcing deletion
- Design delete UI to disable the action on category nodes
When it happens
Trigger: Invoking delete logic on a CategoryViewModel — e.g. generic delete handlers that iterate all selected tree nodes including categories, or code setting IsDeleted on a category.
Common situations: Selecting a whole category in the editor and pressing Delete; batch-deletion scripts that do not filter tree-node types.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- The asset directory cannot be null before deleting an asset.
- The asset mount point cannot be renamed
- Unable to find the base
- Unable to find the graph corresponding to the base part
- The base is unset for the current node.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f33c6628a7427134.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Core.Assets.Editor/ViewModel/CategoryViewModel.cs:41
{
Name = name;
Content = new SortedObservableCollection<TChildren>(childComparer);
}
public sealed override string Name { get; set; }
public SortedObservableCollection<TChildren> Content { get; }
public override bool IsEditable => false;
IEnumerable ICategoryViewModel.Content => Content;
public override string TypeDisplayName => "Category";
protected override void UpdateIsDeletedStatus()
{
if (IsDeleted)
throw new InvalidOperationException("A category cannot be deleted");
}
}
public abstract class CategoryViewModel<TParent, TChildren> : CategoryViewModel<TChildren>
{
protected CategoryViewModel(string name, TParent parent, SessionViewModel session, IComparer<TChildren> childComparer = null)
: base(name, session, childComparer)
{
Parent = parent;
}
public TParent Parent { get; }
}
public class PackageCategoryViewModel : CategoryViewModel<PackageViewModel>, IChildViewModel
{
public PackageCategoryViewModel(string name, SessionViewModel session, IComparer<PackageViewModel> childComparer = null)
: base(name, session, childComparer)View on GitHub (pinned to 96fad776d2)