stride3d/stride · error · NotSupportedException

Unsupported type in array binary operation

Error message

Unsupported type in array binary operation: {otherType}

What it means

BinaryOperation on array-typed values applies the operation element-by-element. The 'other' operand must be an array of the same type (element extracted per index) or a scalar (broadcast). Any other type for the other operand triggers NotSupportedException.

Solutions

  1. Ensure both array operands have identical type and size, or use a scalar for broadcast
  2. Loop over elements explicitly in the shader instead of relying on array operators
  3. Cast or restructure one operand to match the other's array type
  4. Check that array element types match exactly (including signedness)

Example fix

// before (HLSL)
float a[4]; float b[8];
var c = a + b;
// after
float a[4]; float b[4];
var c = a + b; // elementwise
Defensive patterns

Strategy: type-guard

Validate before calling

// Only allow array+same-array or array+scalar binary ops
if (left is ArrayType at && right is not (ArrayType aeq when aeq == at) && right is not ScalarType)
    throw new ShaderSemanticException($"Cannot apply operator between array {left} and {right}");

Type guard

bool IsArrayOpCompatible(ArrayType a, SymbolType other) => other is ArrayType o && o == a || other is ScalarType;

Try / catch

try { var r = BinaryOperation(table, context, left, op, right, info); }
catch (NotSupportedException ex) when (ex.Message.StartsWith("Unsupported type in array binary operation")) { throw new ShaderSemanticException("Array binary operations require same-type arrays or scalar broadcast", ex); }

Prevention

When it happens

Trigger: Binary operation between an array value and a mismatched type (different array type/size, struct, vector) where leftType is ArrayType.

Common situations: Adding arrays of different lengths or element types; mixing array and vector in shader math; generated code assuming implicit array broadcasting rules.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:272

        // Can indirectly happen inside struct (SDSL specific)
        var arrayType = leftType as ArrayType ?? rightType as ArrayType;
        if (arrayType != null)
        {
            var arrayValue = leftType is ArrayType ? left : right;
            var otherType = leftType is ArrayType ? rightType : leftType;
            var otherValue = leftType is ArrayType ? right : left;

            Span<int> arrayValues = stackalloc int[arrayType.Size];
            for (int i = 0; i < arrayType.Size; ++i)
            {
                var memberValue = Buffer.Insert(Position++, new OpCompositeExtract(context.GetOrRegister(arrayType.BaseType), context.Bound++, arrayValue.Id, [i])).ToValue();
                var otherMemberValue = otherType switch
                {
                    // If the other value is also a struct of same type, extract its value
                    ArrayType otherArrayType when otherArrayType == arrayType
                        => Buffer.Insert(Position++, new OpCompositeExtract(context.GetOrRegister(arrayType.BaseType), context.Bound++, otherValue.Id, [i])).ToValue(),
                    ScalarType => otherValue,
                    _ => throw new NotSupportedException($"Unsupported type in array binary operation: {otherType}"),
                };
                arrayValues[i] = leftType is StructType
                    ? BinaryOperation(table, context, memberValue, op, otherMemberValue, info, name).Id
                    : BinaryOperation(table, context, otherMemberValue, op, memberValue, info, name).Id;
            }

            return Buffer.Insert(Position++, new OpCompositeConstruct(context.GetOrRegister(arrayType), resultId, [.. arrayValues])).ToValue();
        }

        (var operandType, var resultType) = AnalyzeBinaryOperation(table, leftType, op, rightType, info) ?? throw new InvalidOperationException("Type of binary operation could not be determined");

        // TODO: Some specific cases where one of the operands doesn't need to have exact same type as resultType (such as shift in OpShiftRightLogical, or signedness for some other operations)
        //       We'll need to review those cases
        left = Convert(context, left, operandType);
        right = Convert(context, right, operandType);

        var resultTypeId = context.GetOrRegister(resultType);

View on GitHub (pinned to 96fad776d2)