{"record":{"id":"f98a06d440af26ff","repo":"stride3d/stride","slug":"only-32-effect-slots-are-currently-allowed-for-meshes","errorCode":null,"errorMessage":"Only 32 effect slots are currently allowed for meshes","messagePattern":"Only 32 effect slots are currently allowed for meshes","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Rendering/Rendering/RootEffectRenderFeature.cs","lineNumber":372,"sourceCode":"        {\n            return effectSlots[renderStage.Index];\n        }\n\n        /// <summary>\n        /// Creates a slot for storing a particular effect instantiation (per RenderObject).\n        /// </summary>\n        /// As an example, we could have main shader (automatically created), GBuffer shader and shadow mapping shader.\n        /// <returns></returns>\n        public EffectPermutationSlot CreateEffectPermutationSlot(string effectName)\n        {\n            // Allocate effect slot\n            // TODO: Should we allow/support this to be called after Initialize()?\n            int slot;\n            if (!effectPermutationSlots.TryGetValue(effectName, out slot))\n            {\n                if (effectPermutationSlots.Count >= 32)\n                {\n                    throw new InvalidOperationException(\"Only 32 effect slots are currently allowed for meshes\");\n                }\n\n                slot = effectPermutationSlots.Count;\n                effectPermutationSlots.Add(effectName, slot);\n\n                // Add render effect slot\n                RenderData.ChangeDataMultiplier(RenderEffectKey, EffectPermutationSlotCount);\n            }\n\n            return new EffectPermutationSlot(slot);\n        }\n\n        /// <summary>\n        /// This is a subpart of effect permutation preparation:\n        ///  set the shader classes that are going to be responsible to compute extended render target colors.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        private void PrepareRenderTargetExtensionsMixins(RenderDrawContext context)","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Rendering/Rendering/RootEffectRenderFeature.cs#L354-L390","documentation":"RootEffectRenderFeature maps each effect (by name) to a bit-flag permutation slot stored in a 32-bit mask (effectPermutationSlots). Registering a 33rd distinct effect would overflow the slot encoding, so CreateEffectPermutationSlot throws InvalidOperationException instead of corrupting render state selection.","triggerScenarios":"Calling CreateEffectPermutationSlot with more than 32 distinct effect names on a single RootEffectRenderFeature — e.g. many MaterialPass/effect variations registered dynamically, or RenderStages collection changes (RenderStages_CollectionChanged) adding slots repeatedly at runtime.","commonSituations":"Large projects with dozens of material effect permutations on one render feature; runtime-added render stages each registering their own effect; forgetting that slot allocation is per-feature, not global.","solutions":["Reduce the number of distinct effect permutations: merge variants into a single effect with a parameter/displacement instead of separate effect names","Split your objects across multiple RenderFeatures/RenderStages so each feature stays under 32 slots","Audit dynamically added render stages/features that call CreateEffectPermutationSlot at runtime and remove unused ones","Reuse existing effect slots by passing effect names already registered (effectPermutationSlots dedupes by name)"],"exampleFix":"// before\nforeach (var effectName in allEffectNames) // > 32 names\n    feature.CreateEffectPermutationSlot(effectName);\n// after\nforeach (var effectName in allEffectNames.Take(32))\n    feature.CreateEffectPermutationSlot(effectName);\n// move remaining effects to a second render feature","handlingStrategy":"validation","validationCode":"if (effectNames.Distinct().Count() > 32)\n    throw new InvalidOperationException(\"Split effects across multiple render features (max 32 slots).\");","typeGuard":null,"tryCatchPattern":"try\n{\n    feature.CreateEffectPermutationSlot(effectName);\n}\ncatch (InvalidOperationException)\n{\n    Logger.Warning(\"Effect slot limit reached; merging effect variants\");\n}","preventionTips":["Audit distinct effect names per feature early","Merge variants with material parameters instead of separate effects","Distribute effects across multiple render features/stages"],"tags":["rendering","effects","limits"],"backgroundTag":"value-out-of-range","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}