stride3d/stride · error · InvalidOperationException
No composition was supplied for
Error message
No composition was supplied for '{variable.Key}', declared as '{variable.Value.Type}' by shader '{shader.ShaderName}', while merging the mixin node '{currentCompositionPath ?? "<root>"}' (root: {mixinNode.IsRoot}). That node only has [{string.Join(", ", mixinSource.Compositions.Keys)}]. A `stage compose` is the usual cause: the shader declaring it was promoted to this node, but its value was supplied at a nested composition path and nothing carried it up. What it means
When merging a mixin node, every composition-type variable (pointer to ShaderSymbol or array thereof) declared by the shader must have a supplied composition. If mixinSource.Compositions lacks the key, the mixer throws a descriptive InvalidOperationException instead of a bare dictionary KeyNotFoundException, hinting that a `stage compose` promotion left the value at a nested path.
Solutions
- Supply the missing composition in the mixin tree, e.g. mixinTree["Key"] = otherShaderSource
- Remove the `stage compose`/promotion so the declaration matches where values are provided
- Fix key spelling so it matches the composed variable name
- Check the error's list of available keys to see what the node actually has
Example fix
// before
var shader = new ShaderMixinSource { Mixins = { baseShader } }; // missing composition for 'stream'
// after
var shader = new ShaderMixinSource { Mixins = { baseShader } };
shader.Compositions.Add("stream", childShaderSource); // matches declared compose variable Defensive patterns
Strategy: try-catch
Validate before calling
foreach (var kv in declaredComposeVariables)
if (!mixinSource.Compositions.ContainsKey(kv.Key))
throw new InvalidOperationException($"Missing composition for '{kv.Key}'"); Try / catch
try { result = mixer.MergeSDSL(tree); }
catch (InvalidOperationException ex) when (ex.Message.Contains("No composition was supplied for")) {
fixCompositionKey(ex, mixinTree); // message lists available keys
} Prevention
- Populate every compose slot declared by mixed shaders
- Keep composition keys in sync when renaming shader channels
- Avoid `stage compose` unless values are hoisted to the promoted node's path
When it happens
Trigger: MergeSDSL/MergeMixinNode encounters a shader declaring `compose X` (or stage-composed) variable while the current mixin source provides no entry for that key; the declaring shader was promoted to this node via `stage compose` but its value was only supplied at a nested composition path; a composition key typo in the mixin tree.
Common situations: Forget ting to set a required compose slot on a ShaderSource/MixinNode before mixing; renaming a composition channel in the shader but not in the hosting code; using `stage compose` inheritance where the parent expects the child's value hoisted to the root path.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Composition variable
- importing stage-only methods/variables is only possible at…
- Could not find cbuffer member link info for
- [Color] attribute can only be applied on float3/float4…
- Unsupported float vector size
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/4803cc3419230a3b.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.cs:337
var mixinNode = new MixinNode(stage, currentCompositionPath);
var contextStart = context.Count;
// Merge all classes from mixinSource.Mixins in main buffer
ProcessMixinClasses(globalContext, context, buffer, mixinSource, mixinNode);
BuildTypesAndMethodGroups(globalContext, context, buffer, mixinNode);
// Compositions (recursive)
foreach (var shader in mixinNode.Shaders)
{
foreach (var variable in shader.Variables)
{
if (variable.Value.Type is PointerType pointer && pointer.BaseType is ShaderSymbol or ArrayType { BaseType: ShaderSymbol })
{
// Every piece of context needed to act on this is in scope, and the dictionary
// indexer would throw a bare "The given key was not present" instead.
if (!mixinSource.Compositions.TryGetValue(variable.Key, out var compositionMixins))
throw new InvalidOperationException(
$"No composition was supplied for '{variable.Key}', declared as '{variable.Value.Type}' by shader '{shader.ShaderName}', "
+ $"while merging the mixin node '{currentCompositionPath ?? "<root>"}' (root: {mixinNode.IsRoot}). "
+ $"That node only has [{string.Join(", ", mixinSource.Compositions.Keys)}]. "
+ $"A `stage compose` is the usual cause: the shader declaring it was promoted to this node, "
+ $"but its value was supplied at a nested composition path and nothing carried it up.");
var isCompositionArray = pointer.BaseType is ArrayType { BaseType: ShaderSymbol };
if (!isCompositionArray && compositionMixins.Length != 1)
throw new InvalidOperationException($"Composition variable {variable.Key} is not an array but had {compositionMixins.Length} entries");
var compositionResults = new MixinNode[compositionMixins.Length];
for (int i = 0; i < compositionMixins.Length; ++i)
{
var localKey = variable.Key;
if (isCompositionArray)
localKey += $"[{i}]";
// TODO: Review: it seems like Stride compose variable the opposite way that we expectView on GitHub (pinned to 96fad776d2)