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.

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)

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.