stride3d/stride · error · NotImplementedException

Can't convert operand to type

Error message

Can't convert operand to type {typeof(T)}

What it means

SpvLiteral.To<T>() converts the literal operand's raw words into a requested managed type T. If T does not match any of the explicitly supported literal shapes (the tmp is not a recognized literal type), the method throws NotImplementedException naming the requested type. Only conversions compiled into SpvLiteral are supported.

Solutions

  1. Use the concrete literal type returned by the operand's Kind and decode Words yourself
  2. Add a conversion branch for the missing type in SpvLiteral.To<T> and Unsafe.As to it
  3. Cast via an intermediate supported type (e.g. int or (int,int) pairs) and reinterpret
  4. Check SpvLiteral source for the supported type list before choosing T

Example fix

// before
var value = operand.To<MyVector4>();
// after
var pairs = operand.To<LiteralArray<(int, int)>>();
var floats = pairs.Items.Select(p => BitConverter.Int32BitsToSingle(p.Item1)).ToArray();
Defensive patterns

Strategy: type-guard

Validate before calling

if (operand.Kind is not (OperandKind.LiteralInteger or OperandKind.LiteralNumber or OperandKind.LiteralString))
    throw new NotSupportedException($"Kind {operand.Kind} has no To<T> mapping");

Type guard

bool IsConvertible<T>(SpvLiteral lit) => lit is not null && SupportedLiteralTypes.Contains(typeof(T));

Try / catch

try { return operand.To<T>(); }
catch (NotImplementedException ex)
{
    logger.LogWarning(ex, "No To<T> mapping for {Type}", typeof(T));
    return DecodeManually(operand.Words);
}

Prevention

When it happens

Trigger: Calling operand.To<SomeType>() where SomeType is not one of the handled literal types (e.g. To<string>, To<SomeCustomStruct>, or an unlisted LiteralArray element type), even though the operand itself parsed fine.

Common situations: Requesting a friendly .NET type for a literal the library has no mapping for (e.g. LiteralContextualWord or unusual LiteralArray tuple shapes); assuming To<T> is generic over all SPIR-V literal kinds.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Spirv/SpvLiteral.cs:168

                var result = LiteralArray<float>.From(Words);
                return Unsafe.As<LiteralArray<float>, T>(ref result);
            }
            else if (tmp is LiteralArray<double>)
            {
                var result = LiteralArray<double>.From(Words);
                return Unsafe.As<LiteralArray<double>, T>(ref result);
            }
            else if (tmp is LiteralArray<bool>)
            {
                var result = LiteralArray<bool>.From(Words);
                return Unsafe.As<LiteralArray<bool>, T>(ref result);
            }
            else if (tmp is LiteralArray<(int, int)>)
            {
                var result = LiteralArray<(int, int)>.From(Words);
                return Unsafe.As<LiteralArray<(int, int)>, T>(ref result);
            }
            else throw new NotImplementedException("Can't convert operand to type " + typeof(T));
        }
        else throw new NotImplementedException($"Can't convert operand to type {typeof(T)}");
        return tmp;
    }

    public override string ToString()
    {
        return Kind switch
        {
            OperandKind.LiteralString => To<LiteralString>().Value,
            OperandKind.IdRef => $"%{Words[0] + Offset}",
            OperandKind.IdResultType => $"%{Words[0] + Offset}",
            OperandKind.PairLiteralIntegerIdRef => $"{Words[0]} %{Words[0] + Offset}",
            OperandKind.MemoryAccess => $"{ToEnum<Specification.MemoryAccessMask>()}",
            OperandKind.MemoryModel => $"{ToEnum<Specification.MemoryModel>()}",
            OperandKind.MemorySemantics => $"{ToEnum<Specification.MemorySemanticsMask>()}",
            OperandKind.AccessQualifier => $"{ToEnum<Specification.AccessQualifier>()}",
            OperandKind.AddressingModel => $"{ToEnum<Specification.AddressingModel>()}",

View on GitHub (pinned to 96fad776d2)