stride3d/stride · error · InvalidOperationException
Can't cast between array of different sizes
Error message
Can't cast between array of different sizes (cast from {valueType} to {castType}) What it means
When converting between array types with the same base element type, sizes must match; only Size == -1 (undetermined size from incomplete generics) is allowed to pass through unchecked. A definite size mismatch (e.g. float[3] to float[4]) cannot be lowered, so Convert throws InvalidOperationException.
Solutions
- Make both arrays the same length
- Declare the target/parameter size to match the source array (or use the same constant)
- Wrap the fixed-size array in a type with matching size before conversion
- If the size is genuinely dynamic, model it via generics or a runtime-length construct supported by the compiler
Example fix
// before float[4] a = (float[4])float3Array; // different sizes // after float[3] a = (float[3])float3Array; // sizes match
Defensive patterns
Strategy: validation
Validate before calling
if (valueType is ArrayType a1 && castType is ArrayType a2 && a1.BaseType == a2.BaseType && a1.Size != -1 && a1.Size != a2.Size)
throw new InvalidOperationException($"Array size mismatch {a1.Size} vs {a2.Size}"); Type guard
bool ArraysMatch(ArrayType a, ArrayType b) => a.BaseType == b.BaseType && (a.Size == -1 || b.Size == -1 || a.Size == b.Size);
Try / catch
try { converted = Builder.Convert(value, castType); }
catch (InvalidOperationException ex) when (ex.Message.Contains("array of different sizes"))
{ /* reject the call or resize the array at source */ } Prevention
- Keep array lengths consistent between producers and consumers
- Declare parameter sizes to match actual data
- Validate sizes after generics instantiation
When it happens
Trigger: Calling Convert where both types are ArrayType with equal base types but different known sizes (a1.Size != -1 && a1.Size != a2.Size).
Common situations: Passing an array of the wrong length to a shader function or parameter; changing an array constant's length without updating its consumer; generics instantiation leaving stale sizes.
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 types
- 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/30d563326a7f0f5d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:501
public SpirvValue Convert(SpirvContext context, in SpirvValue value, in SymbolType castType)
{
var valueId = value.Id;
var valueType = context.ReverseTypes[value.TypeId];
var originalType = valueType;
// No conversion necessary?
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)));
}
View on GitHub (pinned to 96fad776d2)