stride3d/stride · error · InvalidOperationException
Generic argument ( ) for could not be resolved during mix…
Error message
Generic argument {i} ({expr}) for {classSource.ClassName} could not be resolved during mix phase What it means
When instantiating a generic shader during the mix phase, each ConstantExpression in classSource.GenericArguments must TryEvaluate to a non-null constant so it can be converted to a string via ShaderClassSource.ConvertGenericArgToString. If any argument cannot be evaluated to a constant, the builder throws InvalidOperationException naming the argument index, expression, and class.
Solutions
- Provide concrete constant expressions (literals or previously resolved constants) for every generic argument.
- Import the shader whose generic parameter the expression references so it can be substituted before the mix phase.
- Evaluate the argument earlier in the pipeline (ResolveStep.Compile) and store the resolved value in classSource.GenericArguments.
Example fix
// before
var source = new ShaderClassSource("MyShader", new GenericParamExpr("Parent", 0));
// after
var source = new ShaderClassSource("MyShader", new LiteralExpr(4.0f)); Defensive patterns
Strategy: validation
Validate before calling
for (int i = 0; i < classSource.GenericArguments.Length; i++)
if (!classSource.GenericArguments[i].TryEvaluate(out var v) || v is null)
throw new ArgumentException($"Generic argument {i} of {classSource.ClassName} must be a compile-time constant"); Type guard
bool IsConcrete(ConstantExpression e) => e.TryEvaluate(out var v) && v is not null;
Try / catch
try { var result = builder.InstantiateGenericShader(loader, classSource, macros); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be resolved during mix phase")) { /* substitute generics earlier or supply literals */ } Prevention
- Only pass literal/constant generic arguments at instantiation sites
- Resolve dependent generics (e.g. Parent.N) before the mix phase
- Validate all generic arguments with TryEvaluate before calling the builder
When it happens
Trigger: Calling GetOrLoadShader / InstantiateGenericShader with a ShaderClassSource whose GenericArguments still contain unresolved GenericParamExpr or symbolic expressions at mix phase.
Common situations: Instantiating `MyShader<Parent.N>` where Parent's generic N was never substituted because Parent wasn't imported; passing an expression referencing a runtime value instead of a compile-time constant; nested generic instantiations where an inner argument stayed symbolic.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- During mix phase, shaders generics are expected to be fully…
- Not enough generic parameters specified when instantiating
- Exception of type 'System.NotImplementedException' was…
- Can't process constant
- Could not resolve generic arguments
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/55e3044a22a06deb.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs:814
/// <param name="classSource">The generics parameters should be in <see cref="parentBuffer"/>.</param>
/// <param name="macros"></param>
/// <param name="resolveStep"></param>
/// <returns></returns>
/// <param name="parentBuffer"></param>
public static ShaderBuffers GetOrLoadShader(IExternalShaderLoader shaderLoader, ShaderClassInstantiation classSource, ReadOnlySpan<ShaderMacro> macros, ResolveStep resolveStep, SpirvContext context)
{
if (resolveStep == ResolveStep.Mix && classSource.GenericArguments.Length > 0)
{
// At mix time, generics are fully resolved — resolve to string values
// and use the value-based path which caches to shaderLoader.Cache (persistent)
var genericValues = new string[classSource.GenericArguments.Length];
for (int i = 0; i < genericValues.Length; i++)
{
var expr = classSource.GenericArguments[i];
if (expr.TryEvaluate(out var constantValue) && constantValue is not null)
genericValues[i] = ShaderClassSource.ConvertGenericArgToString(constantValue);
else
throw new InvalidOperationException($"Generic argument {i} ({expr}) for {classSource.ClassName} could not be resolved during mix phase");
}
var result = GetOrLoadShader(shaderLoader, classSource.ClassName, genericValues, macros);
// PostProcess: update classSource (same as GenericResolverFromInstantiatingBuffer.PostProcess)
var classNameWithGenerics = $"{classSource.ClassName}<{string.Join(",", genericValues)}>";
classSource.ClassName = classNameWithGenerics;
classSource.GenericArguments = [];
return result;
}
return GetOrLoadShader(shaderLoader, classSource.ClassName, new GenericResolverFromInstantiatingBuffer(classSource, resolveStep, context), macros);
}
public static ShaderBuffers GetOrLoadShader(IExternalShaderLoader shaderLoader, string className, string[]? genericValues, ReadOnlySpan<ShaderMacro> macros)
{
if (genericValues is null)View on GitHub (pinned to 96fad776d2)