stride3d/stride · error · InvalidOperationException
Can't find a base method for
Error message
Can't find a base method for {methodGroupEntry.Name} What it means
For a base call within the same mixin, the mixer walks the method group's Methods list backwards to find the implementation registered just before the current shader's (the direct parent). If no earlier implementation exists, there is no base method to call — the current shader provides the base-most implementation of that method group.
Solutions
- Remove the base call — the current shader is the base-most implementation.
- Add a concrete implementation of the method in a parent shader in the inheritance chain.
- Ensure the parent shader is actually composed (ShaderIndex ordering) before this shader.
- Give the method a default body instead of leaving it abstract if a base behavior is expected.
Example fix
// before: base shader declares method, derived calls base.Method()
void Method() { base.Method(); } // no base impl
// after
void Method() { /* own implementation, no base call */ } Defensive patterns
Strategy: validation
Validate before calling
// A base call requires a strictly earlier implementation in the method group
bool hasBase = methodGroup.Methods.Any(m => m.ShaderIndex < currentShaderIndex);
if (isBase && !hasBase)
throw new InvalidOperationException($"'{methodGroup.Name}' has no base implementation; remove the base call or add a parent override"); Try / catch
try { var mixed = mixer.Process(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Can't find a base method"))
{
log.Error(ex, "base.Method() called in the base-most implementation; drop the call or add a concrete parent implementation");
throw;
} Prevention
- Only call base.Method() when a parent shader in the chain provides a concrete body.
- After refactoring inheritance chains, re-audit base calls at every level.
- Do not call base on methods declared abstract in all ancestors.
- Compile shaders in CI to catch these during development.
When it happens
Trigger: ShaderMixer constructor handles a base call (isBase == true) on a non-stage method group; the backward scan over methodGroupEntry.Methods finds no method with a ShaderIndex before the caller's, leaving baseMethodFound == false.
Common situations: Calling base.Method() in the first (root) shader that declares the method; the parent shader no longer overrides the method after a refactor; method declared abstract in all ancestors so no concrete base exists.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Method was found but a base call can't be performed on a…
- Struct not found in shader
- Could not find compositions for expression
- External variable not found
- Can't find function in current mixin
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/2d47265fad06750b.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.cs:1062
// (if we were to allow them later, we would need to tweak following detection code as ShaderIndex comparison is only valid for items within the same MixinNode)
if (foundInStage)
throw new InvalidOperationException($"Method {methodGroupEntry.Name} was found but a base call can't be performed on a stage method from a non-stage method");
// Is it a base call? if yes, find the direct parent
// Let's find the method in same group just before ours
bool baseMethodFound = false;
for (int j = methodGroupEntry.Methods.Count - 1; j >= 0; --j)
{
if (methodGroupEntry.Methods[j].Shader.ShaderIndex < currentShader.ShaderIndex)
{
selectedMethod = methodGroupEntry.Methods[j];
baseMethodFound = true;
break;
}
}
if (!baseMethodFound)
throw new InvalidOperationException($"Can't find a base method for {methodGroupEntry.Name}");
}
if ((selectedMethod.Flags & FunctionFlagsMask.Abstract) != 0)
throw new InvalidOperationException($"Trying to call an abstract method {selectedMethod.Shader.ShaderName}.{methodGroupEntry.Name}");
functionId = selectedMethod.MethodId;
memberAccesses.Add(memberAccess.ResultId, functionId);
}
else
{
throw new InvalidOperationException($"Member {memberAccess.Member} not found");
}
SetOpNop(i.Data.Memory.Span);
}
else if (i.Data.Op == Op.OpFunction && (OpFunction)i is { } function && temp[index + 1].Op == Op.OpFunctionMetadataSDSL && (OpFunctionMetadataSDSL)temp[index + 1] is { } functionInfo)
{
if (!mixinNode.MethodGroups.TryGetValue(function.ResultId, out var methodGroupEntry))View on GitHub (pinned to 96fad776d2)