stride3d/stride · error · ArgumentNullException

Blendmap parameter cannot be null for a child layer

Error message

Blendmap parameter cannot be null for a child layer

What it means

MaterialGeneratorContext.PushLayer builds the blend-layer tree during shader generation. Every layer except the top-level one must know how it blends with its parent, so if a child layer is pushed with a null blendMap it throws ArgumentNullException for the blendMap parameter.

Solutions

  1. Pass a non-null blend map (e.g. an IMaterialBlendLayer with a valid blending operation) when pushing child layers
  2. Restructure so only the top-level layer is pushed without a blend map
  3. Set the blending in your MaterialBlendLayer (e.g. opacity/multiply/add) before PushLayer
  4. If a child should inherit without blending, use a default blend map like opaque/multiply instead of null

Example fix

// before: child layer without blend map
context.PushLayer(childLayer, null); // throws when nested
// after: supply a blend map for child layers
context.PushLayer(childLayer, new MaterialBlendLayer(context, blendMap) { BlendMap = blendMap });
Defensive patterns

Strategy: validation

Validate before calling

if (context.CurrentLayer != null && blendMap == null)
    blendMap = new MaterialBlendMap(); // or supply an explicit blend operation
context.PushLayer(layer, blendMap);

Type guard

bool NeedsBlendMap(MaterialGeneratorContext ctx) => ctx.CurrentLayer != null;

Try / catch

try { context.PushLayer(layer, blendMap); }
catch (ArgumentNullException ex)
{
    logger.LogError(ex, "Child layer pushed without blend map");
    context.PushLayer(layer, defaultBlendMap);
}

Prevention

When it happens

Trigger: Calling PushLayer(null) when another layer is already open (currentLayerContext != null) — i.e. pushing a child/nested layer without specifying its blend map, typically from a custom material descriptor with nested material layers.

Common situations: Custom IMaterialDescriptor with nested layers forgetting to supply a blending operation (e.g. MaterialBlendLayer with null BlendLayers map); copying sample code but omitting the blend map for inner layers.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/Materials/MaterialGeneratorContext.cs:215

            {
                throw new InvalidOperationException("Cannot PopMaterial more than PushMaterial");
            }
            return materialStack.Pop();
        }

        /// <summary>
        /// Pushes a new layer with the specified blend map.
        /// </summary>
        /// <param name="blendMap">The blend map used by this layer.</param>
        public void PushLayer(IComputeScalar blendMap)
        {
            if (Step != MaterialGeneratorStep.GenerateShader)
                return;

            // We require a blend layer expect for the top level one.
            if (currentLayerContext != null && blendMap == null)
            {
                throw new ArgumentNullException(nameof(blendMap), "Blendmap parameter cannot be null for a child layer");
            }

            var newLayer = new MaterialBlendLayerContext(this, currentLayerContext, blendMap);
            if (currentLayerContext != null)
            {
                currentLayerContext.Children.Add(newLayer);
            }
            currentLayerContext = newLayer;
        }

        /// <summary>
        /// Pops the current layer.
        /// </summary>
        public void PopLayer()
        {
            if (Step != MaterialGeneratorStep.GenerateShader)
                return;

View on GitHub (pinned to 96fad776d2)