apache/skywalking · error · IllegalArgumentException

Rank {rank} doesn't exist in the previous ranks {ranks}

Error message

Rank {rank} doesn't exist in the previous ranks {ranks}

What it means

Once the rank set of a sum_histogram_percentile metric is locked in the current time window, SumHistogramPercentileFunction checks each incoming rank with ranks.include(rank). This branch fires when the count matches but a specific rank value is not in the locked set — e.g. locked [50,75,90] receives [50,75,95].

Source

Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunction.java:119

                    "Incompatible BucketedValues [" + value + "] for current PercentileFunction[" + summation + "]");
            }
        }

        for (final int rank : value.getRanks()) {
            if (rank <= 0) {
                throw new IllegalArgumentException("Illegal rank value " + rank + ", must be positive");
            }
        }

        if (ranks.size() > 0) {
            if (ranks.size() != value.getRanks().length) {
                throw new IllegalArgumentException(
                    "Incompatible ranks size = [" + value.getRanks().length + "] for current PercentileFunction[" + ranks
                        .size() + "]");
            } else {
                for (final int rank : value.getRanks()) {
                    if (!ranks.include(rank)) {
                        throw new IllegalArgumentException(
                            "Rank " + rank + " doesn't exist in the previous ranks " + ranks);
                    }
                }
            }
        } else {
            for (final int rank : value.getRanks()) {
                ranks.add(rank);
            }
        }

        this.entityId = entity.id();

        String template = "%s";
        if (CollectionUtils.isNotEmpty(value.getBucketedValues().getLabels())) {
            template  = value.getBucketedValues().getLabels() + ":%s";
        }
        final long[] values = value.getBucketedValues().getValues();
        for (int i = 0; i < values.length; i++) {

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Align all rank values exactly across every producer of the metric
  2. Restart all OAP nodes together after the config change so a fresh window locks the new ranks
  3. Treat the percentile rank list as part of the metric contract: change it only with a coordinated rollout or a new metric name

Example fix

# before — first window input locks {50,75,90}, later input sends {50,75,95}
# after — all inputs use {50,75,90,99}
percentile(50, 75, 90, 99) -> sum_histogram_percentile
Defensive patterns

Strategy: validation

Validate before calling

IntList locked = function.getRanks();
int[] incoming = argument.getRanks();
if (locked.size() > 0 && Arrays.stream(incoming).anyMatch(r -> !locked.include(r))) {
    log.warn("Rank {} not in locked set {}; dropping", Arrays.toString(incoming), locked);
    return;
}

Try / catch

Catch IllegalArgumentException around accept(), log both rank sets, drop the sample; alert if mismatches persist across windows (indicates config drift, not a transient).

Prevention

When it happens

Trigger: A later input in the same window passes a rank value that was not in the first-accepted rank list, while the total count happens to match.

Common situations: Changing one percentile value (90 -> 95) in MAL config during a rolling upgrade; two agents with different firmware versions reporting the same metric name.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/263063cd73a58ad9. Report an issue: GitHub.