stride3d/stride · error · ArgumentNullException

registeredBuilders

Error message

registeredBuilders

What it means

The ShaderMixinContext constructor throws ArgumentNullException("registeredBuilders") when the dictionary mapping shader names to IShaderMixinBuilder instances is null. Without this registry the context cannot resolve mixin builders by name. This is a fail-fast constructor guard.

Solutions

  1. Pass a non-null dictionary (use ShaderMixinManager.RegisteredBuilders or an empty Dictionary<string, IShaderMixinBuilder>)
  2. Ensure the registry is initialized before context construction
  3. Use ShaderMixinManager.Register to populate builders rather than a hand-rolled null dictionary

Example fix

// before
var ctx = new ShaderMixinContext(tree, parameters, lazyRegistry?.Value); // may be null
// after
var builders = lazyRegistry?.Value ?? new Dictionary<string, IShaderMixinBuilder>();
var ctx = new ShaderMixinContext(tree, parameters, builders);
Defensive patterns

Strategy: validation

Validate before calling

if (registeredBuilders is null) registeredBuilders = new Dictionary<string, IShaderMixinBuilder>();

Type guard

static bool HasBuilderRegistry(Dictionary<string, IShaderMixinBuilder> b) => b != null;

Try / catch

try { var ctx = new ShaderMixinContext(tree, parameters, builders); }
catch (ArgumentNullException ex) when (ex.ParamName == "registeredBuilders") { throw new InvalidOperationException("Builder registry must be initialized", ex); }

Prevention

When it happens

Trigger: Calling new ShaderMixinContext(mixinTree, compilerParameters, null) — e.g. when building a fresh registry asynchronously and passing it before initialization, or when aDI/lookup returned null.

Common situations: Custom compiler hosts that forget to register builder dictionaries; passing a variable that is populated only later (race with initialization).

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Effects/ShaderMixinContext.cs:44

        private readonly ShaderMixinSource currentMixinSourceTree;

        /// <summary>
        /// Initializes a new instance of the <see cref="ShaderMixinContext" /> class.
        /// </summary>
        /// <param name="mixinTree">The mixin tree.</param>
        /// <param name="compilerParameters">The default property container.</param>
        /// <param name="registeredBuilders">The registered builders.</param>
        /// <exception cref="System.ArgumentNullException">compilerParameters
        /// or
        /// registeredBuilders</exception>
        public ShaderMixinContext(ShaderMixinSource mixinTree, ParameterCollection compilerParameters, Dictionary<string, IShaderMixinBuilder> registeredBuilders)
        {
            if (mixinTree == null) throw new ArgumentNullException("mixinTree");
            if (compilerParameters == null)
                throw new ArgumentNullException("compilerParameters");

            if (registeredBuilders == null)
                throw new ArgumentNullException("registeredBuilders");

            // TODO: use a copy of the compilerParameters?
            this.currentMixinSourceTree = mixinTree;
            this.compilerParameters = compilerParameters;
            this.registeredBuilders = registeredBuilders;
            this.parameterCollections = new Stack<ParameterCollection>();
        }

        /// <summary>
        /// Gets or sets the child effect.
        /// </summary>
        /// <value>The child effect.</value>
        public string ChildEffectName { get; set; }

        /// <summary>
        /// Pushes the current parameters collection being used.
        /// </summary>
        /// <typeparam name="T">Type of the parameter collection</typeparam>

View on GitHub (pinned to 96fad776d2)