{"record":{"id":"ef2a2368591cc6fd","repo":"apache/skywalking","slug":"single-to-single-left-result-is-empty-or-has-more","errorCode":null,"errorMessage":"Single to Single, left result is empty or has more than one value.","messagePattern":"Single to Single, left result is empty or has more than one value\\.","errorType":"exception","errorClass":"IllegalExpressionException","httpStatus":null,"severity":"error","filePath":"oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LROp.java","lineNumber":97,"sourceCode":"                                                          ExpressionResult singleRight,\n                                                          int opType, LROp calculate) throws IllegalExpressionException {\n        if (!singleLeft.isLabeledResult() && !singleRight.isLabeledResult()) { // no labeled with no labeled\n            return single2SingleNoLabeled(singleLeft, singleRight, opType, calculate);\n        } else if (singleLeft.isLabeledResult() && !singleRight.isLabeledResult()) { // labeled with no labeled\n            return many2OneBinaryOp(singleLeft, singleRight, opType, calculate);\n        } else if (!singleLeft.isLabeledResult() && singleRight.isLabeledResult()) { // no labeled with labeled\n            return one2ManyBinaryOp(singleLeft, singleRight, opType, calculate);\n        } else { // labeled with labeled\n            return single2SingleLabeled(singleLeft, singleRight, opType, calculate);\n        }\n    }\n\n    private static ExpressionResult single2SingleNoLabeled(ExpressionResult singleLeft,\n                                                          ExpressionResult singleRight,\n                                                          int opType, LROp calculate) throws IllegalExpressionException {\n        if (singleLeft.getResults().isEmpty() ||\n            singleLeft.getResults().get(0).getValues().size() != 1) {\n            throw new IllegalExpressionException(\"Single to Single, left result is empty or has more than one value.\");\n        }\n\n        if (singleRight.getResults().isEmpty() ||\n            singleRight.getResults().get(0).getValues().size() != 1) {\n            throw new IllegalExpressionException(\"Single to Single, right result is empty or has more than one value.\");\n        }\n\n        ExpressionResult result = new ExpressionResult();\n        MQEValue mqeValue = new MQEValue();\n        MQEValues mqeValues = new MQEValues();\n        mqeValues.getValues().add(mqeValue);\n        result.getResults().add(mqeValues);\n        result.setType(ExpressionResultType.SINGLE_VALUE);\n\n        MQEValue left = singleLeft.getResults().get(0).getValues().get(0);\n        MQEValue right = singleRight.getResults().get(0).getValues().get(0);\n        //return null if one of them is empty\n        if (left.isEmptyValue() || right.isEmptyValue()) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LROp.java#L79-L115","documentation":"Thrown by LROp.single2SingleNoLabeled when a binary arithmetic operation (+, -, *, /, ...) is applied to two SINGLE_VALUE operands but the LEFT operand's results list is empty, or its first MQEValues holds a number of values other than exactly 1. The MQE runtime models a scalar as exactly one MQEValues with exactly one MQEValue; anything else is not a valid scalar and the operation refuses to guess which value to use.","triggerScenarios":"An MQE expression like 'metricA / metricB' (or scalar op scalar) where the left sub-expression was typed SINGLE_VALUE (e.g. produced by aggregation like sum(), or a literal) but its results collection is empty or contains multiple values. This path is only reached when NEITHER side is a labeled result (single2SingleBinaryOp, LROp.java:81-82).","commonSituations":"A metric query returns no data for the left operand (empty results) while its type is still SINGLE_VALUE; mixing a scalar metric with a relabeled/labeled metric so the type detection misclassifies it; upgrading OAP versions where a metric's expression result shape changed; querying a metric name that exists in the schema but has never received data.","solutions":["Verify the left operand of the binary expression actually returns exactly one value, e.g. run the left side alone as an MQE query and inspect results[0].values length","Wrap the left operand in an aggregation that guarantees a single value, such as sum(metricA) or avg(metricA), instead of using the raw metric","If the left operand is empty because no data exists yet, guard the expression or accept the IllegalExpressionException as the documented empty-input signal","Check for label manipulation (relabels/onLabel) on the left metric that changed its result shape from scalar to labeled, and adjust which side carries the labels"],"exampleFix":"// before\nquery: service_sla / service_cpm\n// after (force single values on both sides)\nquery: sum(service_sla) / sum(service_cpm)","handlingStrategy":"validation","validationCode":"ExpressionResult left = mqeService.eval(leftExpr);\nboolean ok = left.getResults().size() == 1\n    && left.getResults().get(0).getValues().size() == 1\n    && left.getType() == ExpressionResultType.SINGLE_VALUE\n    && !left.getResults().get(0).getValues().get(0).isEmptyValue();","typeGuard":null,"tryCatchPattern":"catch (IllegalExpressionException e) { /* surface e.getMessage() to the query client; message names the offending side */ }","preventionTips":["Always aggregate raw metrics (sum/avg/latest) before using them as scalar operands","Run each operand alone first when composing a new MQE binary expression","Treat empty results on a scalar operand as a data-availability problem, not a syntax problem"],"tags":["mqe","query-engine","metrics","binary-op"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}