{"record":{"id":"0c5c7663b6d9c160","repo":"stride3d/stride","slug":"type-conversion-from-originaltype-to-casttype-failed-after","errorCode":null,"errorMessage":"Type conversion from {originalType} to {castType} failed after expansion (current type: {valueType})","messagePattern":"Type conversion from (.+?) to (.+?) failed after expansion \\(current type: (.+?)\\)","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs","lineNumber":684,"sourceCode":"        {\n            case (ScalarType, VectorType v2):\n                result = Insert(new OpCompositeConstruct(context.GetOrRegister(v2), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, v2.Size).ToArray())));\n                valueType = v2;\n                break;\n            case (ScalarType, MatrixType m2):\n                result = Insert(new OpCompositeConstruct(context.GetOrRegister(new VectorType(m2.BaseType, m2.Rows)), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, m2.Rows).ToArray())));\n                result = Insert(new OpCompositeConstruct(context.GetOrRegister(m2), context.Bound++, new LiteralArray<int>(Enumerable.Repeat(result, m2.Columns).ToArray())));\n                valueType = m2;\n                break;\n            case (VectorType, MatrixType m2):\n                // rebuild type\n                result = Insert(new OpCompositeConstruct(context.GetOrRegister(m2), context.Bound++, new LiteralArray<int>(values)));\n                valueType = m2;\n                break;\n        }\n\n        if (valueType != castType)\n            throw new NotImplementedException($\"Type conversion from {originalType} to {castType} failed after expansion (current type: {valueType})\");\n\n        return new SpirvValue(result, context.GetOrRegister(castType));\n    }\n\n    public SpirvValue CallFunction(SymbolTable table, SpirvContext context, Symbol functionSymbol, Span<int> parameters)\n    {\n        // Note: Overload should have been chosen before\n        if (functionSymbol.Type is FunctionGroupType)\n            throw new InvalidOperationException();\n\n        var functionType = (FunctionType)functionSymbol.Type;\n        var fcall = Buffer.InsertData(Position++, new OpFunctionCall(context.GetOrRegister(functionType.ReturnType), context.Bound++, functionSymbol.IdRef, [.. parameters]));\n        return new(fcall, functionSymbol.Id.Name);\n    }\n}\n\n\n","sourceCodeStart":666,"sourceCodeEnd":702,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs#L666-L702","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.).","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."],"exampleFix":"// before (shader)\nuint3x3 m = (uint3x3)float3x3f;\n// after\nuint3 r0 = (uint3)f[0]; uint3 r1 = (uint3)f[1]; uint3 r2 = (uint3)f[2];","handlingStrategy":"try-catch","validationCode":"bool sameShape(SymbolType a, SymbolType b) => a.GetType() == b.GetType(); // plus element/size equality","typeGuard":"bool ConvertWillFail(SymbolType original, SymbolType target) => original is MatrixType mo && target is MatrixType mt && (mo.Rows != mt.Rows || mo.Columns != mt.Columns);","tryCatchPattern":"try { result = builder.Convert(table, context, value, castType); }\ncatch (NotImplementedException e) when (e.Message.Contains(\"failed after expansion\"))\n{ Log.Error($\"Unsupported cast {value} -> {castType}\"); throw; }","preventionTips":["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."],"tags":["spirv","conversion-failure","not-implemented","shader-compilation"],"backgroundTag":"method-not-implemented","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}