stride3d/stride · error · InvalidOperationException

A serializer factory selector must be sealed before being…

Error message

A serializer factory selector must be sealed before being used.

What it means

GetSerializer throws InvalidOperationException if the selector was not sealed before use. Sealing finalizes the factory list; using an unsealed selector could yield inconsistent serializer selection and break caching, so the library refuses to operate until Seal() is called.

Solutions

  1. Call Seal() on the selector after adding all factories and before any serialization/deserialization.
  2. Ensure initialization completes even on error paths (try/finally or explicit init method).
  3. Use the standard Serializer construction path that seals the selector automatically.
  4. Check for swallowed exceptions earlier in setup that skipped the Seal call.
  5. Guard usage: assert selector is sealed in your wrapper before serializing.

Example fix

// before
var selector = new SerializerFactorySelector();
selector.TryAddFactory(new MyFactory());
serializer = new Serializer(selector); // GetSerializer later throws: not sealed
// after
var selector = new SerializerFactorySelector();
selector.TryAddFactory(new MyFactory());
selector.Seal();
serializer = new Serializer(selector);
Defensive patterns

Strategy: validation

Validate before calling

// assert before use
System.Diagnostics.Debug.Assert(selectorSealed, "Call Seal() on the SerializerFactorySelector before serializing");

Try / catch

try { var s = selector.GetSerializer(ctx, descriptor); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must be sealed")) { throw new InvalidOperationException("Serializer was used before Seal() — finish initialization first", ex); }

Prevention

When it happens

Trigger: Calling GetSerializer(context, typeDescriptor) on a SerializerFactorySelector whose Seal() was never invoked — typically a selector built manually or wired into a Serializer without finishing registration/sealing.

Common situations: Custom serializer setup code that adds factories but forgets Seal(); DI-created selectors where no one calls Seal; partially completed initialization after an earlier exception aborted setup.

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


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

Appendix: source

Thrown at sources/core/Stride.Core.Yaml/Serialization/SerializerFactorySelector.cs:40

        {
            if (factory == null) throw new ArgumentNullException(nameof(factory));
            if (isSealed) throw new InvalidOperationException("Cannot add a factory to a serializer factory selector once it is sealed.");
            if (CanAddSerializerFactory(factory))
            {
                factories.Add(factory);
            }
        }

        /// <inheritdoc/>
        public void Seal()
        {
            isSealed = true;
        }

        /// <inheritdoc/>
        public IYamlSerializable GetSerializer(SerializerContext context, ITypeDescriptor typeDescriptor)
        {
            if (!isSealed) throw new InvalidOperationException("A serializer factory selector must be sealed before being used.");
            IYamlSerializable serializer;

            // First try, with just a read lock
            serializerLock.EnterReadLock();
            var found = serializers.TryGetValue(typeDescriptor.Type, out serializer);
            serializerLock.ExitReadLock();

            if (!found)
            {
                // Not found, let's take exclusive lock and try again
                serializerLock.EnterWriteLock();
                if (!serializers.TryGetValue(typeDescriptor.Type, out serializer))
                {
                    foreach (var factory in factories)
                    {
                        serializer = factory.TryCreate(context, typeDescriptor);
                        if (serializer != null)
                        {

View on GitHub (pinned to 96fad776d2)