stride3d/stride · error · InvalidOperationException
Can't cast between array of different types
Error message
Can't cast between array of different types (cast from {valueType} to {castType}) What it means
When converting between array types whose base element types differ (e.g. int[] to float[]), Convert has no per-element lowering and throws InvalidOperationException. Array casts are only permitted when base types are identical (and sizes match).
Solutions
- Convert the array element-by-element into a new array of the target element type
- Change the source array to the target element type at construction
- Loosen the receiving API to accept the source element type
- Add element-wise conversion support to Convert if this cast should be legal
Example fix
// before float[] f = (float[])intArray; // different element types // after var f = new float[intArray.Length]; for (int i = 0; i < intArray.Length; i++) f[i] = (float)intArray[i];
Defensive patterns
Strategy: type-guard
Validate before calling
if (valueType is ArrayType s && castType is ArrayType d && s.BaseType != d.BaseType)
throw new InvalidOperationException("Convert array elements explicitly before casting"); Type guard
bool ArrayBaseTypesMatch(ArrayType a, ArrayType b) => a.BaseType == b.BaseType;
Try / catch
try { converted = Builder.Convert(value, castType); }
catch (InvalidOperationException ex) when (ex.Message.Contains("array of different types"))
{ /* convert per-element into a new array instead */ } Prevention
- Use a single element type across array pipelines
- Convert elements individually when element type must change
- Avoid int[]/float[] cross-casts in shader code
When it happens
Trigger: Calling Convert where both types are ArrayType but a1.BaseType != a2.BaseType.
Common situations: Casting an int array to a float array in shader code; texture offset/coordinate helpers receiving arrays of the wrong element type; API changes that altered array element type without updating callers.
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
- Can't cast between array of different sizes
- Can't cast between structures
- Can't cast from to (more components)
- Cast only work between numeral types
- Binary operator not supported for element type
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/dc0d416ddf895c43.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:508
if (castType == valueType)
return value;
if (castType is StructType || valueType is StructType)
throw new NotImplementedException($"Can't cast between structures (cast from {valueType} to {castType})");
if (castType is ArrayType a1 && valueType is ArrayType a2)
{
if (a1.BaseType == a2.BaseType)
{
if (a1.Size != -1 && a1.Size != a2.Size)
throw new InvalidOperationException(($"Can't cast between array of different sizes (cast from {valueType} to {castType})"));
// Some sizes are undetermined; this can only happen during compilation due to incomplete generics type
// TODO: do a "check pass" later to make sure this won't happen after generics instantiation?
return value;
}
else
{
throw new InvalidOperationException(($"Can't cast between array of different types (cast from {valueType} to {castType})"));
}
}
if (castType is StreamsType { Kind: var targetKind }
&& valueType is StreamsType { Kind: var sourceKind }
// Note: order is Input, Streams, Output
&& targetKind > sourceKind)
{
return new(InsertData(new OpCopyLogical(context.GetOrRegister(castType), context.Bound++, value.Id)));
}
// We don't support cast with object yet, filter for numeral types
if ((castType is not ScalarType && castType is not VectorType && castType is not MatrixType)
|| (valueType is not ScalarType && valueType is not VectorType && valueType is not MatrixType))
throw new NotImplementedException($"Cast only work between numeral types (cast from {valueType} to {castType})");
// One entry per column of the SPIR-V matrix (i.e. per HLSL row), since MatrixType.Columns
// is the OpTypeMatrix column count and MatrixType.Rows the size of each column vector.View on GitHub (pinned to 96fad776d2)