stride3d/stride · error · NotSupportedException

Unsupported type for non-pointer indexer

Error message

Unsupported type {currentValueType} for non-pointer indexer

What it means

Thrown when compiling a non-pointer indexer: the current value type being indexed must be a matrix (yields a vector), a vector (yields a scalar), or an array (yields its element type). Any other type reaching the indexer — e.g. a struct or scalar — falls through the switch and throws this NotSupportedException at Expression.cs:1409.

Solutions

  1. Fix the shader expression so only vectors, matrices, or arrays are subscripted.
  2. Check the inferred currentValueType by simplifying the expression or adding compiler diagnostics, and correct the variable declaration.
  3. If a new type must support indexing, add a mapping arm to the switch at Expression.cs:1409 that produces the element type.

Example fix

// before
float x = 1.0; float v = x[0];        // scalar indexed
// after
float1 xs = float1(1.0); float v = xs[0];  // or use a vector/matrix/array type
Defensive patterns

Strategy: type-guard

Validate before calling

// validate the indexed expression's inferred type before subscripting
if (value is not (MatrixType or VectorType or ArrayType))
    throw new ShaderCompileHint($"Cannot index value of type {value.GetType().Name}");

Type guard

static bool IsIndexable(BaseType t) => t is MatrixType or VectorType or ArrayType;

Try / catch

try { result = CompileExpression(expr, table, compiler); }
catch (NotSupportedException ex) when (ex.Message.Contains("for non-pointer indexer"))
{ diagnostics.Report(expr.Info, ex.Message); }

Prevention

When it happens

Trigger: Using `expr[index]` where expr's inferred type is not MatrixType, VectorType, or ArrayType (scalar, struct, bool, custom type) during SPIR-V compilation.

Common situations: Subscripting a struct or scalar in shader code, mistyping a variable so the compiler infers the wrong kind, or hitting a newly added SDSL type that the indexer path was never extended for.

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

Appendix: source

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

                        }

                        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),
                                VectorType v => v.BaseType,
                                ArrayType a => a.BaseType,
                                _ => throw new NotSupportedException($"Unsupported type {currentValueType} for non-pointer indexer"),
                            }, Specification.StorageClass.Function);
                            break;
                        }

                        // We need to load as a variable to use OpAccessChain
                        var (builder, context) = compiler;
                        var ptrType = context.GetOrRegister(new PointerType(currentValueType, Specification.StorageClass.Function));
                        var functionVariable = builder.AddFunctionVariable(ptrType, context.Bound++);
                        builder.Insert(new OpStore(functionVariable, result.Id, null, []));
                        result = new SpirvValue(functionVariable, ptrType);
                        // Process again the same item with new type
                        var indexerValue = indexer.Index.CompileAsValue(table, compiler);
                        PushAccessChainId(accessChainIds, indexerValue.Id);
                        break;
                    }
                case (PointerType { BaseType: PatchType { BaseType: var t } } p, IndexerExpression indexer):
                    {
                        if (compiler == null)

View on GitHub (pinned to 96fad776d2)