{"record":{"id":"3c7cda4d2eaf15ea","repo":"apache/skywalking","slug":"series-labeled-with-labeled-left-and-right-series","errorCode":null,"errorMessage":"Series Labeled with Labeled, left and right series value size not equal.","messagePattern":"Series Labeled with Labeled, left and right series value size not equal\\.","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":304,"sourceCode":"    }\n\n    private static ExpressionResult seriesLabeledWithLabeled(ExpressionResult seriesLeft,\n                                                             ExpressionResult seriesRight,\n                                                             int opType, LROp calculate) throws IllegalExpressionException {\n        Map<Set<KeyValue>, List<MQEValue>> labelMapR = new HashMap<>();\n        seriesRight.getResults().forEach(mqeValuesR -> {\n            labelMapR.put(new HashSet<>(mqeValuesR.getMetric().getLabels()), mqeValuesR.getValues());\n        });\n        for (MQEValues mqeValuesL : seriesLeft.getResults()) {\n            for (int i = 0; i < mqeValuesL.getValues().size(); i++) {\n                //reserve left metric info, if right metric not exist, set empty value\n                MQEValue valueL = mqeValuesL.getValues().get(i);\n                List<MQEValue> mqeValuesR = labelMapR.get(new HashSet<>(mqeValuesL.getMetric().getLabels()));\n                if (mqeValuesR == null) {\n                    valueL.setEmptyValue(true);\n                } else {\n                    if (mqeValuesR.size() != mqeValuesL.getValues().size()) {\n                        throw new IllegalExpressionException(\"Series Labeled with Labeled, left and right series value size not equal.\");\n                    }\n                    MQEValue valueR = mqeValuesR.get(i);\n                    if (valueL.isEmptyValue() || valueR.isEmptyValue()) {\n                        valueL.setEmptyValue(true);\n                        continue;\n                    }\n                    double newValue = calculate.apply(valueL.getDoubleValue(), valueR.getDoubleValue(), opType);\n                    mqeValuesL.getValues().get(i).setDoubleValue(newValue);\n                }\n            }\n        }\n\n        return seriesLeft;\n    }\n}\n","sourceCodeStart":286,"sourceCodeEnd":320,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LROp.java#L286-L320","documentation":"In LROp.seriesLabeledWithLabeled (both sides labeled TIME_SERIES_VALUES), right label groups are indexed by their label set. For each matched group, the right group's value count must equal the left group's value count (values are paired by index). Unmatched labels are tolerated (left becomes emptyValue), but a matched group with a different length throws.","triggerScenarios":"'labeledSeriesA op labeledSeriesB' where a label combination present on both sides has different point counts on each — e.g. one side's series for that label has missing buckets or a different step.","commonSituations":"Two relabeled metrics whose source series have different cadence for the same label; comparing metrics from different sources (e.g. native SkyWalking metric vs OpenTelemetry-mapped metric) with sparse reporting; gaps introduced by retention/TTl differences per metric.","solutions":["Query each operand alone; for labels present on both sides, compare value counts and find the mismatched label group","Align step, duration, and down-sampling for both metrics","Drop sparse labels via relabels so only dense, matched groups remain","Do the merge client-side keyed on (labels, timestamp) when server-side index alignment is too strict"],"exampleFix":"// before\nquery: relabels(a, tag:(k,v)) / relabels(b, tag:(k,v))  // point counts differ for (k,v)\n// after\nquery: relabels(a, tag:(k,v)) / relabels(b, tag:(k,v))  // with identical step and aligned buckets on both metrics","handlingStrategy":"validation","validationCode":"Map<Set<KeyValue>, Integer> rightSizes = right.getResults().stream()\n    .collect(toMap(g -> new HashSet<>(g.getMetric().getLabels()), g -> g.getValues().size()));\nboolean ok = left.getResults().stream()\n    .allMatch(g -> {\n        Integer n = rightSizes.get(new HashSet<>(g.getMetric().getLabels()));\n        return n == null || n == g.getValues().size();\n    });","typeGuard":null,"tryCatchPattern":"catch (IllegalExpressionException e) { /* matched label groups must have equal point counts */ }","preventionTips":["For matched labels, verify equal point counts on both sides before the binary op","Merge on (labels, timestamp) client-side when alignment cannot be guaranteed"],"tags":["mqe","query-engine","labels","alignment"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}