stride3d/stride · error · ArgumentNullException

serializerSelector

Error message

serializerSelector

What it means

RoutingSerializer's constructor throws ArgumentNullException when passed a null ISerializerFactorySelector. The selector is required to route Read/WriteYaml to the appropriate serializer factory, so a null selector is rejected immediately at construction.

Solutions

  1. Pass a non-null ISerializerFactorySelector instance (e.g. from SerializerSettings).
  2. Initialize the selector before constructing RoutingSerializer.
  3. Fix DI registration so the selector is resolvable.
  4. Assert on the settings object earlier to surface which component produced null.

Example fix

// before
var routing = new RoutingSerializer(null);
// after
var routing = new RoutingSerializer(settings.SerializerFactorySelector);
Defensive patterns

Strategy: type-guard

Validate before calling

if (selector is null) throw new InvalidOperationException("SerializerFactorySelector must be configured before building RoutingSerializer");

Type guard

static bool HasSelector(SerializerSettings s) => s?.SerializerFactorySelector != null;

Try / catch

try { var rs = new RoutingSerializer(selector); } catch (ArgumentNullException ex) { throw new InvalidOperationException("RoutingSerializer requires a selector — check serializer settings initialization", ex); }

Prevention

When it happens

Trigger: new RoutingSerializer(null); passing an uninitialized selector variable; a factory chain builder that returns null for the selector.

Common situations: Manual YamlSerializer pipeline assembly where the settings object's SerializerFactorySelector was never set; DI container failing to resolve the selector; copy-pasted serializer setup code omitting the selector argument.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core.Yaml/Serialization/Serializers/RoutingSerializer.cs:59

// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;

namespace Stride.Core.Yaml.Serialization.Serializers
{
    /// <summary>
    /// This serializer is responsible to route to a specific serializer.
    /// </summary>
    public class RoutingSerializer : ChainedSerializer, IYamlSerializable
    {
        private readonly ISerializerFactorySelector serializerSelector;

        public RoutingSerializer(ISerializerFactorySelector serializerSelector)
        {
            if (serializerSelector == null) throw new ArgumentNullException(nameof(serializerSelector));
            this.serializerSelector = serializerSelector;
        }

        public sealed override object ReadYaml(ref ObjectContext objectContext)
        {
            // If value is not null, use its TypeDescriptor otherwise use expected type descriptor
            var instance = objectContext.Instance;
            var typeDescriptorOfValue = instance != null ? objectContext.SerializerContext.FindTypeDescriptor(instance.GetType()) : objectContext.Descriptor;

            var serializer = serializerSelector.GetSerializer(objectContext.SerializerContext, typeDescriptorOfValue);
            return serializer.ReadYaml(ref objectContext);
        }

        public sealed override void WriteYaml(ref ObjectContext objectContext)
        {
            var serializer = serializerSelector.GetSerializer(objectContext.SerializerContext, objectContext.Descriptor);
            serializer.WriteYaml(ref objectContext);
        }

View on GitHub (pinned to 96fad776d2)