stride3d/stride · error · InvalidOperationException
foreach: collection and variable type not matching
Error message
foreach: collection and variable type not matching
What it means
After resolving the foreach collection's element type, ProcessSymbol compares the loop variable's type (variableType.BaseType, the array's element type) with the declared TypeName's resolved type. If they differ, the foreach body would iterate with a mismatched element type, so this InvalidOperationException is thrown.
Solutions
- Change the loop variable's declared type to exactly match the array element type.
- Use 'var' as the loop variable type so it is inferred from the collection.
- Change the collection's element type if the loop variable type is the intended one.
Example fix
// before
float arr[4];
foreach (int v in arr) { ... }
// after
float arr[4];
foreach (float v in arr) { ... } // or: foreach (var v in arr) Defensive patterns
Strategy: validation
Validate before calling
if (arrayType.BaseType != declaredVariableType)
throw new InvalidOperationException("foreach variable type must equal the array element type"); Type guard
bool ElementTypesMatch(ArrayType arr, SymbolType varType) => arr.BaseType == varType;
Try / catch
try { foreachStmt.ProcessSymbol(table); }
catch (InvalidOperationException ex) when (ex.Message == "foreach: collection and variable type not matching") { reportDiagnostic(foreachStmt.Info, ex.Message); } Prevention
- Prefer 'var' for the foreach loop variable so the type is inferred.
- Avoid relying on implicit numeric conversions inside foreach in SDSL.
- Recheck loop variable types after array type refactors or link substitutions.
When it happens
Trigger: foreach (Type v in arrayOfOtherType) where the explicit loop-variable type differs from the array's element type, e.g. foreach (int v in floatArray).
Common situations: Implicit-conversion expectations carried over from C# (SDSL does not convert here); arrays retyped after refactoring; generic/link substitution changing the array element type at composition time.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- foreach: Array type is expected
- Attribute is not supported
- cbuffer have a mix of stage and non-stage members
- Could not find compositions for expression
- Unable to resolve intrinsic Load for type
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/4312dd5b5c9d3165.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Statements.Flow.cs:81
public override void ProcessSymbol(SymbolTable table)
{
Collection.ProcessSymbol(table);
if (!(Collection.Type is PointerType p && p.BaseType is ArrayType arrayType))
throw new InvalidOperationException("foreach: Array type is expected");
var variableType = new PointerType(arrayType.BaseType, Specification.StorageClass.Function);
Variable.Type = variableType;
if (TypeName.Name != "var")
TypeName.ProcessSymbol(table, variableType);
else
TypeName.Type = arrayType.BaseType;
// TODO: check conversions
if (variableType.BaseType != TypeName.Type)
throw new InvalidOperationException("foreach: collection and variable type not matching");
table.Push();
var variableSymbol = new Symbol(new(Variable.Name, SymbolKind.Variable), Variable.Type, 0, OwnerType: table.CurrentShader);
table.CurrentFrame.Add(Variable.Name, variableSymbol);
Body.ProcessSymbol(table);
SymbolFrame = table.Pop();
}
public override void Compile(SymbolTable table, CompilerUnit compiler)
{
var (builder, context) = compiler;
var collection = Collection.Compile(table, compiler);
if (!(Collection.Type is PointerType p && p.BaseType is ArrayType arrayType))
throw new InvalidOperationException("foreach: Array type is expected");
var variableType = new PointerType(arrayType.BaseType, Specification.StorageClass.Function);
// Since foreach need to be processed and expanded later, we use custom opcodeView on GitHub (pinned to 96fad776d2)