apache/skywalking · error · IllegalExpressionException

Unsupported binary operation

Error message

Unsupported binary operation: {}

What it means

IllegalExpressionException from BinaryOp.doBinaryOp: arithmetic binary operations (+, -, *, /, %) between two sub-results failed, and the message wraps the underlying reason from LROp — in practice 'Unsupported operation.' meaning the combination of ExpressionResultTypes on the left and right operands has no defined arithmetic rule in LROp's type matrix.

Solutions

  1. Read the wrapped message (e.getMessage() of the cause) — it is usually LROp's 'Unsupported operation.' indicating a type-combination problem
  2. Restructure so both sides of the operator are the same shape: metric.sum(dt5m) + metric2.sum(dt5m), or wrap list results in an aggregation that reduces them to series/single values first
  3. Apply arithmetic to the inner metric level rather than the outer list level: aggregate_labels(...) + scalar, not topn(...) + scalar
  4. Verify with the MQE docs result-type matrix which operand pairs each operator accepts

Example fix

# before
topn(service_resp_time.sum(dt5m), 10, DES) + 1
# after
topn((service_resp_time.sum(dt5m) + 1).sum(...), 10, DES)  # or compute on the series before topn
Defensive patterns

Strategy: type-guard

Validate before calling

// Before combining: check both sides fit LROp's supported pairs
boolean supportedPair(ExpressionResultType l, ExpressionResultType r) {
    return (l == SINGLE_VALUE && r == SINGLE_VALUE)
        || (isMany(l) && r == SINGLE_VALUE) || (l == SINGLE_VALUE && isMany(r))
        || (l == TIME_SERIES_VALUES && r == TIME_SERIES_VALUES);
}
boolean isMany(ExpressionResultType t) { return t == TIME_SERIES_VALUES || t == SORTED_LIST || t == RECORD_LIST; }

Type guard

boolean isBinarySafe(org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult r) {
    ExpressionResultType t = r.getType();
    return t == ExpressionResultType.SINGLE_VALUE || t == ExpressionResultType.TIME_SERIES_VALUES;
}

Try / catch

catch (IllegalExpressionException e) { /* unwrap cause: usually 'Unsupported operation.' → reshape operands and rebuild the query */ }

Prevention

When it happens

Trigger: MQE arithmetic between incompatible result shapes: e.g. a RECORD_LIST or SORTED_LIST operand combined with a series or another list (LROp supports single-with-single, many-with-one, one-with-many, series-with-series only), or labeled with no-labelled combinations whose intersection is empty for the chosen op.

Common situations: Adding a TopN/SORTED_LIST result to a scalar: 'topn(...) + 1'; mixing trace/log record queries into arithmetic; combining labeled and unlabeled series where the operation has no defined pairing.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/966542e4b19f92b5. Report an issue: GitHub.

Appendix: source

Thrown at oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/BinaryOp.java:32

 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.apache.skywalking.mqe.rt.operation;

import org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult;

public class BinaryOp {
    public static ExpressionResult doBinaryOp(ExpressionResult left,
                                              ExpressionResult right,
                                              int opType) throws IllegalExpressionException {
        try {
            return LROp.doLROp(left, right, opType, BinaryOp::scalarBinaryOp);
        } catch (IllegalExpressionException e) {
            throw new IllegalExpressionException("Unsupported binary operation: " + e.getMessage());
        }
    }

    //scalar with scalar
    private static double scalarBinaryOp(double leftValue, double rightValue, int opType) {
        double calculatedResult = 0;
        switch (opType) {
            case MQEParser.ADD:
                calculatedResult = leftValue + rightValue;
                break;
            case MQEParser.SUB:
                calculatedResult = leftValue - rightValue;
                break;
            case MQEParser.MUL:
                calculatedResult = leftValue * rightValue;
                break;
            case MQEParser.DIV:
                calculatedResult = leftValue / rightValue;

View on GitHub (pinned to 102af09b4a)