stride3d/stride · error · NotSupportedException

Unsupported constant type

Error message

Unsupported constant type: {value.GetType()}

What it means

ConstantExpression.FromValue throws NotSupportedException when given a .NET value whose type has no constant-expression representation. Supported types are int/long/uint/ulong (ints), float/double, bool, and string.

Solutions

  1. Convert the value to a supported type before calling: e.g. cast enum to int, decimal to double, byte/short to int.
  2. Extend FromValue to add a pattern arm for the type if you own the code.
  3. Avoid passing unsupported runtime types as shader constants.

Example fix

// before
var expr = ConstantExpression.FromValue(myEnumValue); // NotSupportedException
// after
var expr = ConstantExpression.FromValue(Convert.ToInt32(myEnumValue));
Defensive patterns

Strategy: type-guard

Validate before calling

static bool IsSupportedConstantType(object v) => v is int or long or uint or ulong or float or double or bool or string;

Type guard

bool IsSupported(object? v) => v is int or long or uint or ulong or float or double or bool or string;

Try / catch

try { expr = ConstantExpression.FromValue(value); }
catch (NotSupportedException ex) { expr = ConstantExpression.FromValue(Convert.ToDouble(value)); }

Prevention

When it happens

Trigger: Calling FromValue with a value of any other type (e.g. char, decimal, Guid, enum boxed as its underlying-but-unsupported shape, user struct) — often from generic constants in SDSL/SPIR-V codegen.

Common situations: Passing C# enum or decimal constant into shader constant emission; accidentally passing a boxed object; switching compiler versions where narrower types (byte/short) are no longer implicitly matched.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs:69

        var tempContext = new SpirvContext();
        var resultId = Emit(tempContext);
        return SpirvContext.ExtractConstantFromBuffer(resultId, tempContext.GetBuffer());
    }

    /// <summary>
    /// Create a ConstantExpression from a concrete runtime value.
    /// </summary>
    public static ConstantExpression FromValue(object value) => value switch
    {
        int i => new IntConstExpr(i),
        uint u => new IntConstExpr(u),
        long l => new IntConstExpr(l),
        ulong u => new IntConstExpr((long)u),
        float f => new FloatConstExpr(f),
        double d => new FloatConstExpr(d),
        bool b => new BoolConstExpr(b),
        string s => new StringConstExpr(s),
        _ => throw new NotSupportedException($"Unsupported constant type: {value.GetType()}")
    };

    /// <summary>
    /// Parse a SPIR-V constant ID into a ConstantExpression tree.
    /// Replaces ExtractConstantFromBuffer for array sizes and generic arguments.
    /// </summary>
    public static ConstantExpression ParseFromBuffer(int constantId, SpirvBuffer buffer, SpirvContext context)
    {
        if (!buffer.TryGetInstructionById(constantId, out var inst))
            throw new InvalidOperationException($"Cannot find instruction for id {constantId}");

        return ParseInstruction(inst, buffer, context);
    }

    private static ConstantExpression ParseInstruction(OpDataIndex inst, SpirvBuffer buffer, SpirvContext context)
    {
        switch (inst.Op)
        {

View on GitHub (pinned to 96fad776d2)