{"record":{"id":"2c51db7f0407aadd","repo":"stride3d/stride","slug":"unsupported-type-in-array-binary-operation-othertype","errorCode":null,"errorMessage":"Unsupported type in array binary operation: {otherType}","messagePattern":"Unsupported type in array binary operation: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs","lineNumber":272,"sourceCode":"        // Can indirectly happen inside struct (SDSL specific)\n        var arrayType = leftType as ArrayType ?? rightType as ArrayType;\n        if (arrayType != null)\n        {\n            var arrayValue = leftType is ArrayType ? left : right;\n            var otherType = leftType is ArrayType ? rightType : leftType;\n            var otherValue = leftType is ArrayType ? right : left;\n\n            Span<int> arrayValues = stackalloc int[arrayType.Size];\n            for (int i = 0; i < arrayType.Size; ++i)\n            {\n                var memberValue = Buffer.Insert(Position++, new OpCompositeExtract(context.GetOrRegister(arrayType.BaseType), context.Bound++, arrayValue.Id, [i])).ToValue();\n                var otherMemberValue = otherType switch\n                {\n                    // If the other value is also a struct of same type, extract its value\n                    ArrayType otherArrayType when otherArrayType == arrayType\n                        => Buffer.Insert(Position++, new OpCompositeExtract(context.GetOrRegister(arrayType.BaseType), context.Bound++, otherValue.Id, [i])).ToValue(),\n                    ScalarType => otherValue,\n                    _ => throw new NotSupportedException($\"Unsupported type in array binary operation: {otherType}\"),\n                };\n                arrayValues[i] = leftType is StructType\n                    ? BinaryOperation(table, context, memberValue, op, otherMemberValue, info, name).Id\n                    : BinaryOperation(table, context, otherMemberValue, op, memberValue, info, name).Id;\n            }\n\n            return Buffer.Insert(Position++, new OpCompositeConstruct(context.GetOrRegister(arrayType), resultId, [.. arrayValues])).ToValue();\n        }\n\n        (var operandType, var resultType) = AnalyzeBinaryOperation(table, leftType, op, rightType, info) ?? throw new InvalidOperationException(\"Type of binary operation could not be determined\");\n\n        // 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)\n        //       We'll need to review those cases\n        left = Convert(context, left, operandType);\n        right = Convert(context, right, operandType);\n\n        var resultTypeId = context.GetOrRegister(resultType);\n","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs#L254-L290","documentation":"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.","triggerScenarios":"Binary operation between an array value and a mismatched type (different array type/size, struct, vector) where leftType is ArrayType.","commonSituations":"Adding arrays of different lengths or element types; mixing array and vector in shader math; generated code assuming implicit array broadcasting rules.","solutions":["Ensure both array operands have identical type and size, or use a scalar for broadcast","Loop over elements explicitly in the shader instead of relying on array operators","Cast or restructure one operand to match the other's array type","Check that array element types match exactly (including signedness)"],"exampleFix":"// before (HLSL)\nfloat a[4]; float b[8];\nvar c = a + b;\n// after\nfloat a[4]; float b[4];\nvar c = a + b; // elementwise","handlingStrategy":"type-guard","validationCode":"// Only allow array+same-array or array+scalar binary ops\nif (left is ArrayType at && right is not (ArrayType aeq when aeq == at) && right is not ScalarType)\n    throw new ShaderSemanticException($\"Cannot apply operator between array {left} and {right}\");","typeGuard":"bool IsArrayOpCompatible(ArrayType a, SymbolType other) => other is ArrayType o && o == a || other is ScalarType;","tryCatchPattern":"try { var r = BinaryOperation(table, context, left, op, right, info); }\ncatch (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); }","preventionTips":["Ensure both array operands match in element type and length","Use explicit element loops for cross-size/mixed-type array math","Prefer scalar broadcast over vector/array mixing"],"tags":["shader","array","binary-operation","spirv"],"backgroundTag":"incompatible-source-type","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}