{"record":{"id":"e442d2e391b75d1e","repo":"apache/skywalking","slug":"incompatible-ranks-size-value-getranks-lengt","errorCode":null,"errorMessage":"Incompatible ranks size = [{value.getRanks().length}] for current PercentileFunction[{ranks.size()}]","messagePattern":"Incompatible ranks size = \\[(.+?)\\] for current PercentileFunction\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java","lineNumber":134,"sourceCode":"\n    @Override\n    public void accept(final MeterEntity entity, final PercentileArgument value) {\n        if (dataset.size() > 0) {\n            if (!value.getBucketedValues().isCompatible(dataset)) {\n                throw new IllegalArgumentException(\n                    \"Incompatible BucketedValues [\" + value + \"] for current PercentileFunction[\" + dataset + \"]\");\n            }\n        }\n\n        for (final int rank : value.getRanks()) {\n            if (rank <= 0) {\n                throw new IllegalArgumentException(\"Illegal rank value \" + rank + \", must be positive\");\n            }\n        }\n\n        if (ranks.size() > 0) {\n            if (ranks.size() != value.getRanks().length) {\n                throw new IllegalArgumentException(\n                    \"Incompatible ranks size = [\" + value.getRanks().length + \"] for current PercentileFunction[\" + ranks\n                        .size() + \"]\");\n            } else {\n                for (final int rank : value.getRanks()) {\n                    if (!ranks.include(rank)) {\n                        throw new IllegalArgumentException(\n                            \"Rank \" + rank + \" doesn't exist in the previous ranks \" + ranks);\n                    }\n                }\n            }\n        } else {\n            for (final int rank : value.getRanks()) {\n                ranks.add(rank);\n            }\n        }\n\n        this.entityId = entity.id();\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java#L116-L152","documentation":"Once an AvgHistogramPercentileFunction instance has accepted a rank set (ranks is non-empty), every later accept() must supply the exact same rank count — the persisted 'ranks' column and percentile-reading logic are fixed to that set. A differing length throws 'Incompatible ranks size' (and a differing set of equal size throws the adjacent 'Rank ... doesn't exist' error).","triggerScenarios":"A MAL percentile rule is edited to add or remove a rank (e.g. 50,99 -> 50,90,99) and re-applied while the metric's in-memory/persisted aggregation still carries the old rank set; two rules emit the same percentile metric with different rank lists.","commonSituations":"Hot-reloading percentile rules after editing the percentiles list; copy-pasted metric names across rules with diverging rank configs; upgrading a config that added a default rank.","solutions":["Keep the rank list fixed for the lifetime of the percentile metric name — change ranks only together with a new metric name","If ranks must change, hot-remove the old metric / restart OAP so the function restarts with an empty ranks state","Search all rules for the metric name and make the rank lists identical"],"exampleFix":"# before — hot-edit adds a rank to an existing metric\n  percentiles: 50,99      # original\n  percentiles: 50,90,99   # edited -> Incompatible ranks size = [3] ... [2]\n\n# after — new metric name for the new rank set\n  metric: service_latency_percentile_v2\n  percentiles: 50,90,99","handlingStrategy":"validation","validationCode":"// keep the rank set constant per metric name; validate against the contract before accept\nif (!Arrays.equals(ranks, rankContractFor(metricName))) {\n    log.warn(\"Rank set changed for {} — use a new metric name or reset state\", metricName);\n    return;\n}\npercentileMetric.accept(entity, new PercentileArgument(bucketedValues, ranks));","typeGuard":null,"tryCatchPattern":"try {\n    percentileMetric.accept(entity, percentileArgument);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Incompatible ranks size\")\n            || e.getMessage().contains(\"doesn't exist in the previous ranks\")) {\n        log.error(\"Rank drift on {} — ranks are immutable once accepted\", metricName, e);\n        return;\n    }\n    throw e;\n}","preventionTips":["Consider ranks part of the metric identity: to change them, ship a new metric name","If ranks must change on an existing name, hot-remove the metric or restart OAP so ranks state resets","Define the percentile list once in shared config and reuse it in every rule referencing the metric"],"tags":["meter-system","percentile","mal","hot-reload","config"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}