stride3d/stride · error · InvalidOperationException

The shading model with type

Error message

The shading model with type [{shadingModel.GetType()}] is already added

What it means

MaterialShadingModelCollection is a keyed collection that stores at most one shading model per concrete type. Add throws InvalidOperationException when a shading model of the same runtime type is added twice, to prevent duplicate shader builders for the same shading model.

Solutions

  1. Check ShadingModelCollection.ContainsKey(typeof(T)) before calling Add, or just index the existing entry
  2. Remove the existing shading model of that type first if replacement is intended
  3. If multiple variants are needed, create distinct shading model subclasses instead of two instances of the same type

Example fix

// before
material.ShadingModelCollection.Add(pbr);
material.ShadingModelCollection.Add(pbr2); // throws: same type
// after
if (!material.ShadingModelCollection.ContainsKey(typeof(PBRShadingModel)))
    material.ShadingModelCollection.Add(pbr);
Defensive patterns

Strategy: validation

Validate before calling

if (material.ShadingModelCollection.ContainsKey(shadingModel.GetType()))
    return; // or remove first

Type guard

static bool CanAdd(Material m, MaterialShadingModel sm) => !m.ShadingModelCollection.ContainsKey(sm.GetType());

Try / catch

try { material.ShadingModelCollection.Add(shadingModel); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is already added")) {
    // already present: treat as idempotent
}

Prevention

When it happens

Trigger: Calling material.ShadingModelCollection.Add on a MaterialShadingModel instance whose type is already present in the collection, e.g. adding two instances of PBRShadingModel, or re-adding the same instance.

Common situations: Configuring a material in code and adding a shading model that the material already has (e.g. from a copied/cloned material or a constructor default); repeated setup code executed on material reload.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/Materials/MaterialShadingModelCollection.cs:29

    /// <summary>
    /// Stores a collection of shading model used by a layer and allow to compare if a layer can be blend by attributes (if
    /// shading model doesn't change) or by shading (if shading model is different).
    /// </summary>
    internal sealed class MaterialShadingModelCollection : Dictionary<Type, (IMaterialShadingModelFeature ShadingModel, ShadingModelShaderBuilder ShaderBuilder)>
    {
        /// <summary>
        /// Adds the specified shading model associated with source to this collection.
        /// </summary>
        /// <typeparam name="T">Type of the shading model</typeparam>
        /// <param name="shadingModel">The shading model</param>
        public ShadingModelShaderBuilder Add<T>(T shadingModel) where T : class, IMaterialShadingModelFeature
        {
            if (shadingModel == null) throw new ArgumentNullException(nameof(shadingModel));

            // Check that we cannot have the same type of shading model multiple times
            if (ContainsKey(shadingModel.GetType()))
            {
                throw new InvalidOperationException($"The shading model with type [{shadingModel.GetType()}] is already added");
            }

            var result = new ShadingModelShaderBuilder();
            this[shadingModel.GetType()] = (shadingModel, result);
            return result;
        }

        /// <summary>
        /// Copies the shading models of this instance to the destination instance.
        /// </summary>
        /// <param name="node">The destination collection</param>
        public void CopyTo(MaterialShadingModelCollection node)
        {
            if (node == null) throw new ArgumentNullException(nameof(node));
            foreach (var keyValue in this)
            {
                node[keyValue.Key] = keyValue.Value;
            }

View on GitHub (pinned to 96fad776d2)