stride3d/stride · error · InvalidOperationException
Can't find function in current mixin
Error message
Can't find function {function.Name} in current mixin What it means
When a member access resolves to a known external function, the mixer must bind it to a method group in the current mixin (or its Stage) using the (function name, function type) key. If neither instanceMixinGroup.MethodGroupsByName nor the stage's MethodGroupsByName contains the entry, the function is not implemented in the current mixin hierarchy.
Solutions
- Implement the method with the exact name and matching signature in the current shader mixin.
- Match the function type/signature exactly — overloads are keyed by (name, FunctionType).
- Ensure the stage is attached (instanceMixinGroup.Stage) if the method is defined at stage level.
- Verify the base shader declaring the external function is composed into this shader.
Example fix
// before: shader calls Shade() but never defines it
// after: add implementation in the mixin shader
void Shade() { /* ... */ } // signature must match the declared FunctionType Defensive patterns
Strategy: validation
Validate before calling
// Confirm the mixin implements the external function with a matching signature
if (globalContext.ExternalFunctions.ContainsKey(methodName) &&
!instanceMixinGroup.MethodGroupsByName.ContainsKey((methodName, functionType)) &&
!(instanceMixinGroup.Stage?.MethodGroupsByName.ContainsKey((methodName, functionType)) ?? false))
throw new InvalidOperationException($"Mixin must implement '{methodName}' with signature matching the declared FunctionType"); Try / catch
try { var mixed = mixer.Process(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Can't find function"))
{
log.Error(ex, "External function not implemented in mixin; check name and exact signature (overloads are keyed by FunctionType)");
throw;
} Prevention
- Implement every method required by composed base shaders; keep signatures byte-exact.
- Beware overloads: the method-group key includes the FunctionType, so parameter types must match the declaration.
- Attach the Stage when methods are defined at stage level.
- Add a build-time check that each shader class compiles standalone and in its common compositions.
When it happens
Trigger: ShaderMixer constructor handles an OpMemberAccess with a FunctionType result; globalContext.ExternalFunctions contains the member name, but MethodGroupsByName has no (function.Name, functionType) entry in the mixin or its Stage.
Common situations: Calling a method declared/required by a base shader but never overridden or implemented in the mixin; signature mismatch (overload with different parameter types) so the method-group key lookup misses; stage not attached when the method is a stage method.
Related errors
- Trying to call an abstract method
- Struct not found in shader
- Could not find compositions for expression
- External variable not found
- Can't find method group info for
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/8b154406c9b5480f.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.cs:1025
if (!(instanceMixinGroup.Stage != null
&& instanceMixinGroup.Stage.ShadersByName.TryGetValue(shaderName, out shaderInfo)
&& shaderInfo.Variables.TryGetValue(variable.Name, out variableInfo)))
{
throw new InvalidOperationException($"External variable {variable.Name} not found");
}
}
memberAccesses.Add(memberAccess.ResultId, variableInfo.Id);
}
else if (context.ReverseTypes[memberAccess.ResultType] is FunctionType functionType)
{
// In case of functions, OpMemberAccessSDSL.Member could either be a OpFunction or a OpImportFunctionSDSL
var functionId = memberAccess.Member;
if (globalContext.ExternalFunctions.TryGetValue(memberAccess.Member, out var function))
{
// Process member call (composition)
if (!instanceMixinGroup.MethodGroupsByName.TryGetValue((function.Name, functionType), out functionId)
&& (instanceMixinGroup.Stage == null || !instanceMixinGroup.Stage.MethodGroupsByName.TryGetValue((function.Name, functionType), out functionId)))
throw new InvalidOperationException($"Can't find function {function.Name} in current mixin");
}
bool foundInStage = false;
if (!instanceMixinGroup.MethodGroups.TryGetValue(functionId, out var methodGroupEntry))
{
// Try again as a stage method (only if not a base call)
if (instanceMixinGroup.Stage == null || !instanceMixinGroup.Stage.MethodGroups.TryGetValue(functionId, out methodGroupEntry))
throw new InvalidOperationException($"Can't find method group info for {context.Names[functionId]}");
foundInStage = true;
}
// Default: most derived implementation
var selectedMethod = methodGroupEntry.Methods[^1];
// Process base call
if (isBase)
{
// We currently do not allow calling base stage method from a non-stage methodView on GitHub (pinned to 96fad776d2)