stride3d/stride · error · InvalidOperationException
The base is unset for the current node.
Error message
The base is unset for the current node.
What it means
In AssetPropertyGraph's base-node change handling, this InvalidOperationException is thrown when assetNode.BaseNode is null at the moment a BaseNodeChanged event is processed. The handler must reconcile the node with its base, but there is no base node — meaning the node was unlinked from its base while the change event was still being processed, or base linking state is inconsistent. It enforces the internal invariant that this event handler only runs for nodes that actually have a base.
Solutions
- Check assetNode.BaseNode != null before raising/processing the BaseNodeChanged event and skip reconciliation if unset
- Unlink the node from its base before unsubscribing/triggering events in the correct order
- Guard your own refresh logic so it does not fire base-change events after unlinking
- Re-link the node to its base (re-apply the archetype) before reconciling
Example fix
// before OnBaseContentChanged(e, node); // may fire after unlink // after if (assetNode.BaseNode is null) return; // node already unlinked, nothing to reconcile OnBaseContentChanged(e, node);
Defensive patterns
Strategy: type-guard
Validate before calling
if (assetNode.BaseNode is null)
return; // nothing to reconcile; skip raising/processing the base-change event Type guard
bool hasBase = assetNode.BaseNode is not null;
Try / catch
try { ReconcileNode(assetNode); } catch (InvalidOperationException ex) when (ex.Message == "The base is unset for the current node.") { // node was unlinked: skip reconciliation or re-link first } Prevention
- Unlink nodes from their base before tearing down event subscriptions
- Avoid clearing archetype links concurrently with base content refresh
- Check BaseNode for null before triggering reconciliation logic
When it happens
Trigger: Raising/processing a BaseNodeChanged event for a node whose base link was just cleared (UnlinkFromBase), or whose asset never had a base linked; concurrent unlinking while base content changes propagate.
Common situations: Clearing an archetype/base link while base refresh is in flight; programmatic manipulation of Quantum graphs that unlinks nodes without cancelling event subscriptions; race conditions during editor shutdown or asset reload.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Unable to find the base [{AssetItem.Asset.Archetype.Location
- Unable to find the graph corresponding to the base part
- An IObjectNode was expected when processing the path [{path}
- An IMemberNode was expected when processing the path [{path}
- No Collection item identifier associated to the given collec
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/d61e137cbf5df120.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets.Quantum/AssetPropertyGraph.cs:720
private void OnBaseContentChanged(INodeChangeEventArgs e, IGraphNode node)
{
var assetNode = (IAssetNode)node;
// Ignore base change if propagation is disabled.
if (!Container.PropagateChangesFromBase)
return;
if (node.IsReference && e.OldValue?.GetType().IsValueType == false)
{
var oldNode = (IAssetNode?)Container.NodeContainer.GetNode(e.OldValue);
UnlinkFromBase(oldNode);
}
UpdatingPropertyFromBase = true;
var baseNode = assetNode.BaseNode;
if (assetNode.BaseNode is null)
throw new InvalidOperationException("The base is unset for the current node.");
RefreshBase(assetNode, (IAssetNode)baseNode);
ReconcileWithBase((IAssetNode)node);
UpdatingPropertyFromBase = false;
BaseContentChanged?.Invoke(e, node);
}
private void ReconcileWithBaseNode(IAssetNode assetNode, GraphNodePath currentPath, bool reconcileObjectReference, Dictionary<IGraphNode, NodeIndex>? nodesToReset)
{
var memberNode = assetNode as AssetMemberNode;
var objectNode = assetNode as IAssetObjectNodeInternal;
// Non-overridable members should not be reconciled.
if (assetNode?.BaseNode is null || memberNode?.CanOverride == false)
return;
var localValue = assetNode.Retrieve();
var baseValue = assetNode.BaseNode.Retrieve();
View on GitHub (pinned to 96fad776d2)