apache/skywalking · error · IllegalArgumentException
Illegal rank value {rank}, must be positive
Error message
Illegal rank value {rank}, must be positive What it means
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.
Source
Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java:128
@Setter
@Column(name = RANKS, storageOnly = true)
@BanyanDB.MeasureField
private IntList ranks = new IntList(10);
private boolean isCalculated = false;
@Override
public void accept(final MeterEntity entity, final PercentileArgument value) {
if (dataset.size() > 0) {
if (!value.getBucketedValues().isCompatible(dataset)) {
throw new IllegalArgumentException(
"Incompatible BucketedValues [" + value + "] for current PercentileFunction[" + dataset + "]");
}
}
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()) {View on GitHub (pinned to 102af09b4a)
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
Example fix
# before percentiles: 0,50,99 # 0 is illegal # after percentiles: 50,90,99
Defensive patterns
Strategy: validation
Validate before calling
for (int rank : ranks) {
if (rank <= 0) throw new IllegalStateException("Rank must be positive, got " + rank);
}
percentileMetric.accept(entity, new PercentileArgument(bucketedValues, ranks)); Type guard
boolean validRanks(int[] ranks) {
for (int r : ranks) { if (r <= 0) return false; }
return true;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Hand-edited otel-rules YAML with placeholder ranks; templating systems injecting empty/zero values; unit tests with degenerate rank arrays.
Related errors
- Incompatible ranks size = [{value.getRanks().length}] for cu
- Function {} doesn't inherit from Metrics.
- {} has been defined, but calculate function or/are scope typ
- buckets and values can't be null.
- The length of buckets and values should be same.
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/a6c6210a73d56ef5.
Report an issue: GitHub.