stride3d/stride · error · InvalidOperationException

Type conversion from

Error message

Type conversion from {originalType} to {castType} failed during conversion (current type: {valueType})

What it means

Thrown by Builder.Expressions.Convert while iterating the value's rows/components during an element-wise cast. A row value id of 0 (the SPIR-V 'no result' sentinel) means a prior expansion/construct step failed to produce a value, so the conversion is aborted with InvalidOperationException.

Solutions

  1. Identify the originalType->castType pair triggering it and simplify the cast in the shader (cast components manually).
  2. Debug Builder.Expressions.cs expansion logic for that type pair to see why values[i] stays 0.
  3. Check Stride issue tracker for the failing cast combination and update the package.

Example fix

// before (shader)
int2 v = (int2)someComposite;
// after
int2 v = int2((int)someComposite.x, (int)someComposite.y);
Defensive patterns

Strategy: try-catch

Try / catch

try { result = builder.Convert(table, context, value, castType); }
catch (InvalidOperationException e) when (e.Message.StartsWith("Type conversion"))
{ Log.Error($"Convert failed: {e.Message}"); throw; }

Prevention

When it happens

Trigger: During Convert, after the type-expansion loop, one of the values[] entries is 0 (uninitialized/unproduced), indicating the expansion from originalType to valueType silently failed.

Common situations: Casting composite values (vectors/matrices) where the earlier composite expansion produced no result id; usually a bug in a specific type combination rather than the direct cast arguments.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/9c534953823003ff. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:614

                    break;
                }
        }

        if (valueType.GetElementType() != castType.GetElementType())
        {
            // Type casting
            // (process each vector one by one)
            (int elementSize, var castTypeSameSize) = valueType switch
            {
                ScalarType s => (1, (SymbolType)castType.GetElementType()),
                VectorType s => (s.Size, new VectorType(castType.GetElementType(), s.Size)),
                _ => throw new NotSupportedException($"Unsupported type for element-wise cast: {valueType}"),
            };
            for (int i = 0; i < valueCount; ++i)
            {
                var rowValue = values[i];
                if (rowValue == 0)
                    throw new InvalidOperationException($"Type conversion from {originalType} to {castType} failed during conversion (current type: {valueType})");

                var typeCasting = (valueType.GetElementType(), castType.GetElementType()) switch
                {
                    // https://learn.microsoft.com/en-us/windows/win32/direct3d9/casting-and-conversion
                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.Int }) => InsertData(new OpConvertFToS(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),
                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.UInt }) => InsertData(new OpConvertFToU(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),

                    (ScalarType { Type: Scalar.Float }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpFOrdNotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new FloatLiteral(new(32, true, true), 0.0, new()), elementSize).Id)),
                    (ScalarType { Type: Scalar.Int }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpINotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, true), 0, new()), elementSize).Id)),
                    (ScalarType { Type: Scalar.UInt }, ScalarType { Type: Scalar.Boolean }) => InsertData(new OpINotEqual(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue, context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, false), 0, new()), elementSize).Id)),

                    (ScalarType { Type: Scalar.Int }, ScalarType { Type: Scalar.Float }) => InsertData(new OpConvertSToF(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),
                    (ScalarType { Type: Scalar.UInt }, ScalarType { Type: Scalar.Float }) => InsertData(new OpConvertUToF(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue)),

                    (ScalarType { Type: Scalar.Boolean }, ScalarType { Type: Scalar.Int }) => InsertData(new OpSelect(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue,
                                                                                                    context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, true), 1, new()), elementSize).Id,
                                                                                                    context.CreateConstantCompositeVectorRepeat(new IntegerLiteral(new(32, false, true), 0, new()), elementSize).Id)),
                    (ScalarType { Type: Scalar.Boolean }, ScalarType { Type: Scalar.Float }) => InsertData(new OpSelect(context.GetOrRegister(castTypeSameSize), context.Bound++, rowValue,

View on GitHub (pinned to 96fad776d2)