stride3d/stride · error · NotSupportedException

Unsupported symbol type: {symbolType}

Error message

Unsupported symbol type: {symbolType}

What it means

ConvertType maps SDSL parser type symbols (base types, vectors, matrices, scalars) to effect reflection types (EffectParameterType/Class). The switch covers the known set of TypeBase-derived symbols; any other symbolType reaching it has no reflection representation and triggers this NotSupportedException. It is an exhaustiveness guard so new/unknown SDSL type symbols fail loudly instead of producing wrong reflection data.

Solutions

  1. Look at the symbolType value in the message to identify the unhandled type kind.
  2. Add a matching case in the ConvertType switch to translate that symbol type into the correct EffectParameterType/Class.
  3. If the type shouldn't appear here (e.g. textures/samplers in a cbuffer), fix the earlier parsing/collecting stage so those symbols are excluded before ComputeCBufferReflection.
  4. Update or align your Stride version: if the type is new, ensure the reflection converter from the matching version is used.

Example fix

// before
_ => throw new NotSupportedException($"Unsupported symbol type: {symbolType}"),

// after
SamplerType s => new EffectParameterTypeDescription { Class = EffectParameterClass.Object, Type = EffectParameterType.Sampler },
_ => throw new NotSupportedException($"Unsupported symbol type: {symbolType}"),
Defensive patterns

Strategy: validation

Validate before calling

// Check the symbol type is one ConvertType handles before reflection conversion
var supported = symbolType is BaseType or VectorType or MatrixType or ScalarType;
if (!supported) throw new InvalidOperationException($"Type {symbolType} cannot be converted to effect reflection data.");

Type guard

bool IsReflectableType(TypeBase t) => t is BaseType or VectorType or MatrixType or ScalarType;

Try / catch

try { var desc = ConvertType(context, symbolType, typeModifier, alignmentRules); }
catch (NotSupportedException ex) { log.Error($"Reflection conversion failed: {ex.Message}. Ensure only scalars/vectors/matrices reach ConvertType."); throw; }

Prevention

When it happens

Trigger: ConvertType is called (directly, or via ConvertStructType, element-type conversion, or ComputeCBufferReflection) with a symbolType outside the mapped set — e.g. a struct/pointer/sampler/user-defined type symbol or a newly added SDSL type kind that the converter has no case for.

Common situations: A newly introduced SDSL language type not yet handled in ConvertType; a type declaration reaching cbuffer reflection that should have been filtered out earlier (e.g. samplers or textures inside a cbuffer declaration); custom parser extensions producing unknown symbol types.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.CBuffers.cs:420

        {
            return symbolType switch
            {
                ScalarType { Type: Scalar.Boolean } => new EffectTypeDescription { Class = EffectParameterClass.Scalar, Type = EffectParameterType.Bool, RowCount = 1, ColumnCount = 1, ElementSize = 4 },
                ScalarType { Type: Scalar.UInt } => new EffectTypeDescription { Class = EffectParameterClass.Scalar, Type = EffectParameterType.UInt, RowCount = 1, ColumnCount = 1, ElementSize = 4 },
                ScalarType { Type: Scalar.Int } => new EffectTypeDescription { Class = EffectParameterClass.Scalar, Type = EffectParameterType.Int, RowCount = 1, ColumnCount = 1, ElementSize = 4 },
                ScalarType { Type: Scalar.Float } => new EffectTypeDescription { Class = EffectParameterClass.Scalar, Type = EffectParameterType.Float, RowCount = 1, ColumnCount = 1, ElementSize = 4 },
                ScalarType { Type: Scalar.Double } => new EffectTypeDescription { Class = EffectParameterClass.Scalar, Type = EffectParameterType.Double, RowCount = 1, ColumnCount = 1, ElementSize = 8 },
                ArrayType a => ConvertArrayType(context, a, typeModifier, alignmentRules),
                StructType s => ConvertStructType(context, s, alignmentRules),
                // TODO: should we use RowCount instead? (need to update Stride)
                VectorType v => ConvertType(context, v.BaseType, typeModifier, alignmentRules) with { Class = EffectParameterClass.Vector, RowCount = 1, ColumnCount = v.Size },
                // Note: this is HLSL-style so Rows/Columns meaning is swapped
                //       however, for type/class, both TypeModifier and EffectParameterType are following HLSL
                MatrixType m when typeModifier == TypeModifier.ColumnMajor || typeModifier == TypeModifier.None
                    => ConvertType(context, m.BaseType, typeModifier, alignmentRules) with { Class = EffectParameterClass.MatrixColumns, RowCount = m.Columns, ColumnCount = m.Rows },
                MatrixType m when typeModifier == TypeModifier.RowMajor
                    => ConvertType(context, m.BaseType, typeModifier, alignmentRules) with { Class = EffectParameterClass.MatrixRows, RowCount = m.Columns, ColumnCount = m.Rows },
                _ => throw new NotSupportedException($"Unsupported symbol type: {symbolType}"),
            };
        }

        private void ComputeCBufferReflection(MixinGlobalContext globalContext, SpirvContext context, SpirvBuffer buffer)
        {
            var cbuffers = buffer
                .Where(x => x.Op == Op.OpVariableSDSL)
                // Note: MemberIndexOffset is simply a shift in Members index, not something like a byte offset
                .Select(x => (
                    Variable: x,
                    VariableId: x.Data.IdResult!.Value,
                    StructTypePtrId: x.Data.IdResultType!.Value,
                    StructType: context.ReverseTypes[x.Data.IdResultType.Value] is PointerType p && p.StorageClass == Specification.StorageClass.Uniform && p.BaseType is StructuredType s ? s : null,
                    MemberIndexOffset: 0))
                .Where(x => x.StructType != null)
                .ToList();

            foreach (var cbuffer in cbuffers)

View on GitHub (pinned to 96fad776d2)