stride3d/stride · error · KeyNotFoundException

Member was not found in shader

Error message

Member {name} was not found in shader {ShaderName}

What it means

ShaderInfo.FindMember resolves a member name (function or variable) within a merged shader's SPIR-V info. When neither the functions nor the variables dictionaries contain the name, it throws KeyNotFoundException identifying the shader. This indicates the referenced symbol was not imported/duplicated into this shader's range during mixing.

Solutions

  1. Verify the member name spelling against the declaring shader source
  2. Ensure the shader declaring the member is actually mixed in (compose/inherit) for this node
  3. Check that the member isn't stage-only when not at the root mixin (see MergeClassInBuffers)
  4. Inspect ShaderInfo.Variables/Functions dictionaries for available names

Example fix

// before: member not mixed in
var shader = mixer.MergeSDSL(tree, ...); // 'ComputeIt' lives in a shader not composed here
var (id, type) = shaderInfo.FindMember("ComputeIt");
// after: add the composition supplying the shader that declares ComputeIt
mixinTree["ComputeIt"] = loadShader("MyComputeShader");
Defensive patterns

Strategy: try-catch

Validate before calling

if (!shaderInfo.Variables.ContainsKey(memberName) && !shaderInfo.Functions.ContainsKey(memberName))
    throw new ArgumentException($"{memberName} not present in {shaderInfo.ShaderName}");

Type guard

bool HasMember(ShaderInfo info, string name) =>
    info.Variables.ContainsKey(name) || info.Functions.ContainsKey(name);

Try / catch

try { var (id, type) = shaderInfo.FindMember(name); }
catch (KeyNotFoundException ex) when (ex.Message.Contains("was not found in shader")) {
    logMissingMixinMember(name, shaderInfo.ShaderName);
}

Prevention

When it happens

Trigger: Looking up a member by name that the shader never declares; referencing a member declared only in another mixin without proper composition/inheritance; name mismatches after renaming; querying ShaderInfo for symbols stripped because they were stage-only and not imported.

Common situations: Calling a base-class method that the composed shader didn't inherit; typos in member names in compose/inherit directives; accessing a variable from a shader whose stage composition failed.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.ShaderInfo.cs:55

        public int EndInstruction { get; internal set; } = endInstruction;
        public Dictionary<string, List<(int Id, FunctionType Type)>> Functions { get; } = new();
        public Dictionary<string, (int Id, SymbolType Type)> Variables { get; } = new();

        public Dictionary<string, int> StructTypes { get; } = new();

        public (int Id, SymbolType Type) FindMember(string name, FunctionType? functionType = null)
        {
            if (Functions.TryGetValue(name, out var functions))
            {
                foreach (var function in functions)
                {
                    if (function.Type == functionType)
                        return (function.Id, function.Type);
                }
            }
            if (Variables.TryGetValue(name, out var variable))
                return (variable.Id, variable.Type);
            throw new KeyNotFoundException($"Member {name} was not found in shader {ShaderName}");
        }

        public override string ToString() => $"{ShaderName} ({(CompositionPath != null ? $" {CompositionPath} " : "")}{StartInstruction}..{EndInstruction})";
    }

    private void PopulateShaderInfo(MixinGlobalContext globalContext, SpirvContext context, int contextStart, int contextEnd, SpirvBuffer buffer, int shaderStart, int shaderEnd, ShaderInfo shaderInfo, MixinNode mixinNode)
    {
        var removedIds = new HashSet<int>();
        for (var index = shaderStart; index < shaderEnd; index++)
        {
            var i = buffer[index];

            if (i.Data.Op == Op.OpFunction && (OpFunction)i is { } function)
            {
                var functionName = context.Names[function.ResultId];
                var functionType = (FunctionType)context.ReverseTypes[function.FunctionType];
                if (!shaderInfo!.Functions.TryGetValue(functionName, out var functions))
                    shaderInfo.Functions.Add(functionName, functions = new());

View on GitHub (pinned to 96fad776d2)