stride3d/stride · error · QuantumConsistencyException
A collection type
Error message
A collection type
What it means
DefaultNodeBuilder.VisitObject throws QuantumConsistencyException when a node created from an object turns out to be a reference node while its descriptor type is a struct. Quantum expects struct-typed values to be boxed/plain value nodes, not reference nodes, so this signals an internal node-factory/type-descriptor inconsistency.
Solutions
- Inspect the struct type whose descriptor sets IsReference and fix the custom descriptor/factory so structs are not treated as references
- Update Stride.Core packages so Quantum and TypeDescriptor versions match
- If the type should be a class, change the model so the descriptor's type is not a struct
- Catch QuantumConsistencyException during Build and log the offending type to identify the misregistered descriptor
Example fix
// before: custom factory returns a reference node for a struct
public override IObjectNode CreateObjectNode(...) => new ObjectNode(..., isReference: true);
// after: let the default factory box value types
var content = descriptor.Type.IsValueType
? NodeFactory.CreateBoxedNode(this, rootGuid, obj, descriptor)
: NodeFactory.CreateObjectNode(this, rootGuid, obj, descriptor); Defensive patterns
Strategy: validation
Validate before calling
if (descriptor.Type.IsValueType && descriptor.IsReference) throw new InvalidOperationException($"{descriptor.Type} is a struct marked as reference"); Type guard
bool IsValidStructNode(ITypeDescriptor d) => !(d.Type.IsValueType && d.IsReference);
Try / catch
try { builder.Build(obj); } catch (QuantumConsistencyException ex) { logger.LogError(ex, "Quantum inconsistency for {Type}", ex.Object?.GetType()); } Prevention
- Never override node factories to mark structs as references
- Keep Stride.Core.Quantum and Stride.Core.Assemblies versions in sync
- Test graph builds over all struct types in your model
When it happens
Trigger: Visiting an object whose TypeDescriptor reports IsValueType (struct) but NodeFactory.CreateBoxedNode/CreateObjectNode produces a node with IsReference=true, e.g. a type whose descriptor is inconsistent (custom ITypeDescriptor, mismatched metadata) during Build of a NodeContainer.
Common situations: Custom type descriptors or node factories overriding default behavior; struct types registered or resolved through descriptors that mark them as reference types; library version mismatch where IsReference detection changed.
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
- A node of the path is null but is not the last node.
- A reference can only be constructed with the method…
- An error occurred while adding an item to the node, see the…
- An error occurred while adding an item to the node, see the…
- An error occurred while removing an item to the node, see…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6fbb237ef970178a.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Quantum/DefaultNodeBuilder.cs:70
return rootNode!;
}
/// <inheritdoc/>
public override void VisitObject(object obj, ObjectDescriptor descriptor, bool visitMembers)
{
ITypeDescriptor currentDescriptor = descriptor;
bool isRootNode = contextStack.Count == 0;
if (isRootNode)
{
// If we're visiting a value type as "object" we need to use a special "boxed" node.
var content = descriptor.Type.IsValueType ? NodeFactory.CreateBoxedNode(this, rootGuid, obj, descriptor)
: NodeFactory.CreateObjectNode(this, rootGuid, obj, descriptor);
currentDescriptor = content.Descriptor;
rootNode = (IInitializingObjectNode)content;
if (content.IsReference && currentDescriptor.Type.IsStruct())
throw new QuantumConsistencyException("A collection type", "A structure type", rootNode);
PushContextNode(rootNode);
}
if (!PrimitiveTypeFilter.IsPrimitiveType(currentDescriptor.Type))
{
base.VisitObject(obj, descriptor, true);
}
if (isRootNode)
{
PopContextNode();
rootNode!.Seal();
}
}
/// <inheritdoc/>
public override void VisitCollection(IEnumerable collection, CollectionDescriptor descriptor)View on GitHub (pinned to 96fad776d2)