stride3d/stride · error · InvalidOperationException

A reference can only be constructed with the method…

Error message

A reference can only be constructed with the method Reference.CreateReference

What it means

Reference constructors require an internal thread-local counter (CreatingReference) to be active; it is incremented only inside Reference.CreateReference. If a Reference-derived object is constructed directly (new ...) outside that factory, CheckReferenceCreationSafeGuard detects the counter is zero and throws InvalidOperationException, enforcing that every reference is created through the factory.

Solutions

  1. Replace direct construction (new ReferenceEnumerable(...)/new DerivedReference(...)) with a call to Reference.CreateReference.
  2. If you need collection semantics, pass a value of a list/dictionary/set/collection type to CreateReference so it produces a ReferenceEnumerable.
  3. Only call the constructor from within Reference.CreateReference (i.e. subclass code inside the library).

Example fix

// before
var reference = new ReferenceEnumerable(value, nodeIndex);
// after
var reference = (ReferenceEnumerable)Reference.CreateReference(value, value.GetType(), nodeIndex, false);
Defensive patterns

Strategy: type-guard

Validate before calling

var reference = value != null ? Reference.CreateReference(value, value.GetType(), index, isMember) : null;

Type guard

bool SafeToConstruct() => Reference.CheckReferenceCreationSafeGuard is only satisfied inside CreateReference; never call constructors directly — always use Reference.CreateReference.

Try / catch

try { var r = Reference.CreateReference(value, type, index, isMember); }
catch (InvalidOperationException) { /* you bypassed the factory; switch to CreateReference */ }

Prevention

When it happens

Trigger: Instantiating Reference (or a subclass such as ReferenceEnumerable) directly with `new`, instead of calling Reference.CreateReference; this typically happens in custom factories or tests bypassing the factory.

Common situations: Writing a custom IReference implementation or NodeFactory; unit tests constructing ReferenceEnumerable to inspect item references; code copied from older Stride versions where direct construction was tolerated.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/ff7150301a9aeca8. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Quantum/References/Reference.cs:54

            {
                reference = null;
            }
        }

        --CreatingReference.Value;

        return reference;
    }

    private static bool HasCollectionReference(Type type)
    {
        return type.IsArray || ListDescriptor.IsList(type) || DictionaryDescriptor.IsDictionary(type) || SetDescriptor.IsSet(type) || CollectionDescriptor.IsCollection(type);
    }

    internal static void CheckReferenceCreationSafeGuard()
    {
        if (!CreatingReference.IsValueCreated || CreatingReference.Value == 0)
            throw new InvalidOperationException("A reference can only be constructed with the method Reference.CreateReference");
    }
}

View on GitHub (pinned to 96fad776d2)