{"record":{"id":"a6c6210a73d56ef5","repo":"apache/skywalking","slug":"illegal-rank-value-rank-must-be-positive","errorCode":null,"errorMessage":"Illegal rank value {rank}, must be positive","messagePattern":"Illegal rank value (.+?), must be positive","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":128,"sourceCode":"    @Setter\n    @Column(name = RANKS, storageOnly = true)\n    @BanyanDB.MeasureField\n    private IntList ranks = new IntList(10);\n\n    private boolean isCalculated = false;\n\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()) {","sourceCodeStart":110,"sourceCodeEnd":146,"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#L110-L146","documentation":"Percentile ranks are positional percentages (e.g. 50, 75, 99) used by AvgHistogramPercentileFunction to read values at quantiles of the accumulated histogram; a rank of 0 or a negative number is meaningless for that math. accept() validates every element of PercentileArgument.getRanks() and throws before any state is mutated.","triggerScenarios":"A MAL percentile rule declares ranks containing 0 or a negative value — e.g. a copied config where 0 was used as a placeholder, or arithmetic on a templated rank that produced 0/negative; an agent sends a percentile payload with a rank of 0.","commonSituations":"Hand-edited otel-rules YAML with placeholder ranks; templating systems injecting empty/zero values; unit tests with degenerate rank arrays.","solutions":["Set all ranks to positive integers (1-100 style percentiles) in the MAL rule / PercentileArgument","Validate rank arrays at the producer/config boundary (reject non-positive before send)","If the rank list comes from templating, default placeholders to a real rank like 50 instead of 0"],"exampleFix":"# before\n  percentiles: 0,50,99   # 0 is illegal\n\n# after\n  percentiles: 50,90,99","handlingStrategy":"validation","validationCode":"for (int rank : ranks) {\n    if (rank <= 0) throw new IllegalStateException(\"Rank must be positive, got \" + rank);\n}\npercentileMetric.accept(entity, new PercentileArgument(bucketedValues, ranks));","typeGuard":"boolean validRanks(int[] ranks) {\n    for (int r : ranks) { if (r <= 0) return false; }\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Lint MAL rule files for percentile lists containing 0 or negatives before deployment","Never use 0 as a placeholder in templated rank configs — use a valid default like 50","Validate rank arrays in agents/collectors at the emission boundary"],"tags":["meter-system","percentile","validation","mal","config"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}