stride3d/stride · error · NotImplementedException
Type conversion from
Error message
Type conversion from {originalType} to {castType} failed after expansion (current type: {valueType}) What it means
Final sanity check of Builder.Expressions.Convert: after all expansion and element-wise cast steps, if the resulting valueType still differs from the requested castType, the conversion pipeline failed and a NotImplementedException is thrown. It means no case in the big type-pair switch handled this (originalType, castType) combination.
Solutions
- Simplify or split the cast in the shader so each step is a supported combination.
- Add the missing case in Builder.Expressions.cs to expand/retype to castType.
- Search/upgrade Stride for the specific cast combination support.
Example fix
// before (shader) uint3x3 m = (uint3x3)float3x3f; // after uint3 r0 = (uint3)f[0]; uint3 r1 = (uint3)f[1]; uint3 r2 = (uint3)f[2];
Defensive patterns
Strategy: try-catch
Validate before calling
bool sameShape(SymbolType a, SymbolType b) => a.GetType() == b.GetType(); // plus element/size equality
Type guard
bool ConvertWillFail(SymbolType original, SymbolType target) => original is MatrixType mo && target is MatrixType mt && (mo.Rows != mt.Rows || mo.Columns != mt.Columns);
Try / catch
try { result = builder.Convert(table, context, value, castType); }
catch (NotImplementedException e) when (e.Message.Contains("failed after expansion"))
{ Log.Error($"Unsupported cast {value} -> {castType}"); throw; } Prevention
- Avoid exotic matrix retype casts; split them into supported steps.
- Compile shaders early in CI to detect unsupported casts.
- Check Stride's supported conversion matrix before using new type combinations.
When it happens
Trigger: Calling Convert with a type combination for which none of the expansion cases (scalar/vector/matrix) produce exactly castType — e.g. an unhandled matrix-to-different-matrix element retype or a vector with an unhandled element cast.
Common situations: Unusual casts in shader code (mixed element-size changes on composites) or a Stride version lacking support for the combination; surfaces during shader compilation (ConvertTexCoord, CompileSign, etc.).
Related errors
- Exception of type 'System.NotImplementedException' was…
- Cast from to is not implemented
- Cast from to is not implemented
- Type conversion from
- Unsupported int width
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/0c5c7663b6d9c160.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:684
{
case (ScalarType, VectorType v2):
result = Insert(new OpCompositeConstruct(context.GetOrRegister(v2), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, v2.Size).ToArray())));
valueType = v2;
break;
case (ScalarType, MatrixType m2):
result = Insert(new OpCompositeConstruct(context.GetOrRegister(new VectorType(m2.BaseType, m2.Rows)), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, m2.Rows).ToArray())));
result = Insert(new OpCompositeConstruct(context.GetOrRegister(m2), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, m2.Columns).ToArray())));
valueType = m2;
break;
case (VectorType, MatrixType m2):
// rebuild type
result = Insert(new OpCompositeConstruct(context.GetOrRegister(m2), context.Bound++, new LiteralArray<int>(values)));
valueType = m2;
break;
}
if (valueType != castType)
throw new NotImplementedException($"Type conversion from {originalType} to {castType} failed after expansion (current type: {valueType})");
return new SpirvValue(result, context.GetOrRegister(castType));
}
public SpirvValue CallFunction(SymbolTable table, SpirvContext context, Symbol functionSymbol, Span<int> parameters)
{
// Note: Overload should have been chosen before
if (functionSymbol.Type is FunctionGroupType)
throw new InvalidOperationException();
var functionType = (FunctionType)functionSymbol.Type;
var fcall = Buffer.InsertData(Position++, new OpFunctionCall(context.GetOrRegister(functionType.ReturnType), context.Bound++, functionSymbol.IdRef, [.. parameters]));
return new(fcall, functionSymbol.Id.Name);
}
}
View on GitHub (pinned to 96fad776d2)