stride3d/stride · error · NotImplementedException
Cast only work between numeral types
Error message
Cast only work between numeral types (cast from {valueType} to {castType}) What it means
CanConvertScore only supports conversion scoring between numeral types (ScalarType, VectorType, MatrixType). If either the source or target type is anything else (e.g. StreamsType, ArrayType, object), the function throws because the library deliberately filters casts to numeric types.
Solutions
- Restrict the cast to scalar/vector/matrix types on both sides
- Convert via an explicit operation appropriate for the type (e.g. sample a stream into a vector before casting)
- Remove the cast if the value is already the correct type and fix the surrounding type inference
- Extend the conversion logic if this numeric/non-numeric cast should be legitimate
Example fix
// before float x = (float)someStream; // cast from StreamsType // after float x = someStream.Load(0); // or bind stream values via proper stream access
Defensive patterns
Strategy: type-guard
Validate before calling
static bool IsNumeral(SymbolType t) => t is ScalarType or VectorType or MatrixType;
if (!IsNumeral(valueType) || !IsNumeral(castType)) throw new InvalidOperationException("Cast requires numeral types"); Type guard
bool IsNumeralType(SymbolType t) => t is ScalarType or VectorType or MatrixType;
Try / catch
try { score = CanConvertScore(valueType, castType); }
catch (NotImplementedException ex) when (ex.Message.Contains("numeral types"))
{ /* reject the overload or pick a non-cast path */ } Prevention
- Only cast between scalar/vector/matrix values
- Access streams via stream APIs, not casts
- Verify inferred types before invoking conversion scoring
When it happens
Trigger: Requesting a conversion score where valueType or castType is not a ScalarType/VectorType/MatrixType — e.g. casting a stream or array to a numeral type or vice versa.
Common situations: Casting between streams and vectors in shader code; accidentally casting an array to a scalar; overload resolution reaching CanConvertScore with non-numeric candidate types after generics instantiation.
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 array of different types
- Can't cast between structures
- Can't cast from to (more components)
- Binary operator not supported for element type
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f2f44840a9c92e7d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:418
// TODO: do a "check pass" later to make sure this won't happen after generics instantiation?
return 0;
}
else
{
return int.MaxValue;
}
}
if (castType is StreamsType { Kind: var targetKind }
&& valueType is StreamsType { Kind: var sourceKind }
// Note: order is Input, Streams, Output
&& targetKind > sourceKind)
return 1;
// 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})");
var conversionScore = (valueType, castType) switch
{
// Same size
(ScalarType, ScalarType) => 0,
(VectorType v1, VectorType v2) when v1.Size == v2.Size => 0,
(MatrixType m1, MatrixType m2) when m1.Rows == m2.Rows && m1.Columns == m2.Columns => 0,
// Promotion scalar to vector or matrix (replicate value) — more expensive than scalar-to-scalar conversion
(ScalarType, VectorType or MatrixType) => 5,
// Truncation
// Shape-changing truncation (vector/matrix to scalar) costs more than dimension-reducing truncation
// This ensures e.g. mul(float3, float4x4) picks mul_vm(float3, float3x4) over mul_sm(float, float4x4)
(VectorType or MatrixType, ScalarType) => 20,
(VectorType v1, VectorType v2) when v1.Size > v2.Size => 10 + (v1.Size - v2.Size),
(MatrixType m1, MatrixType m2) when (m1.Rows > m2.Rows && m1.Columns >= m2.Columns) || (m1.Rows >= m2.Rows && m1.Columns > m2.Columns) => 10 + (m1.Rows - m2.Rows) + (m1.Columns - m2.Columns),
View on GitHub (pinned to 96fad776d2)