stride3d/stride · error · NotSupportedException

Unsupported base type

Error message

Unsupported base type {p.BaseType} for indexer

What it means

Thrown by the SDSL-to-SPIR-V expression compiler when an indexer accesses a pointer parameter whose base type is neither a matrix nor a vector. The compiler can only derive the pointed-to element type (matrix -> element vector, vector -> scalar) for those shapes, so any other base type hits the switch default and this NotSupportedException is thrown at Expression.cs:1388.

Solutions

  1. Change the shader code so the indexed pointer refers to a vector or matrix (e.g. index the variable before taking a pointer, or declare the buffer element as a vector/matrix).
  2. If arrays/structs must be indexable through pointers, extend the switch in Expression.cs to map ArrayType => a.BaseType (mirroring the non-pointer case at line 1409) and rebuild.
  3. Inspect the offending parameter's declared type in the shader to confirm what BaseType actually resolves to and why.

Example fix

// before (shader)
StructuredBuffer<int> data;
... ptr = &data; ptr[i] ...   // base type is array/other
// after
// index the buffer variable directly, or make the pointer point at a vector/matrix element
Defensive patterns

Strategy: type-guard

Validate before calling

// before indexing a pointer, check its pointee kind in the AST
if (param.BaseType is not MatrixType and not VectorType)
    throw new ShaderCompileHint($"Cannot index pointer to {param.BaseType}; use vector/matrix");

Type guard

static bool IsIndexablePointer(Parameter p) => p.BaseType is MatrixType or VectorType;

Try / catch

try { result = CompileExpression(expr, table, compiler); }
catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported base type"))
{ diagnostics.Report(expr.Info, ex.Message); }

Prevention

When it happens

Trigger: Indexing into a pointer whose pointee is not MatrixType or VectorType (e.g. a pointer to an array, struct, or scalar) inside a SPIR-V compilation of an SDSL expression with `compiler != null`.

Common situations: Writing shader code that subscripts a pointer parameter bound to a non-vector/matrix type, or after type-inference changes make a pointer's BaseType an unexpected kind (array/struct) — often after refactors of the SDSL type system or unusual buffer declarations.

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/69d333a41005ced8. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Expression.cs:1388

                            indexer.Index.ProcessSymbol(table);
                            accessor.Type = new PointerType(t, p.StorageClass);
                            break;
                        }
                        var indexerValue = indexer.Index.CompileAsValue(table, compiler);
                        PushAccessChainId(accessChainIds, indexerValue.Id);
                        break;
                    }
                // Array indexer for vector/matrix
                case (PointerType { BaseType: VectorType or MatrixType } p, IndexerExpression indexer):
                    {
                        if (compiler == null)
                        {
                            indexer.Index.ProcessSymbol(table);
                            accessor.Type = new PointerType(p.BaseType switch
                            {
                                MatrixType m => new VectorType(m.BaseType, m.Rows),
                                VectorType v => v.BaseType,
                                _ => throw new NotSupportedException($"Unsupported base type {p.BaseType} for indexer"),
                            }, p.StorageClass);
                            break;
                        }

                        var indexerValue = indexer.Index.CompileAsValue(table, compiler);
                        PushAccessChainId(accessChainIds, indexerValue.Id);
                        break;
                    }
                // For indexer accessor into non pointer types, we can't use OpCompositeExtract (it expects a constant)
                // So we load the value into a variable and use normal path
                case (ArrayType or VectorType or MatrixType, IndexerExpression indexer):
                    {
                        if (compiler == null)
                        {
                            indexer.Index.ProcessSymbol(table);
                            accessor.Type = new PointerType(currentValueType switch
                            {
                                MatrixType m => new VectorType(m.BaseType, m.Rows),

View on GitHub (pinned to 96fad776d2)