apache/druid · error · IllegalArgumentException

Bucket index out of range (0, )

Error message

Bucket index out of range (0, )

What it means

SpectatorHistogram stores counts indexed by Netflix Spectator PercentileBuckets, which have a fixed length. add(int bucket, long count) validates that the bucket index is within [0, PercentileBuckets.length()) and throws IAE otherwise. This guards the underlying LongAdder map from receiving invalid bucket ids.

Source

Thrown at extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogram.java:305

  }

  void merge(SpectatorHistogram source)
  {
    if (source == null) {
      return;
    }
    Short2LongOpenHashMap writableMap = writableMap();
    for (Short2LongMap.Entry entry : Short2LongMaps.fastIterable(source.readableMap())) {
      writableMap.addTo(entry.getShortKey(), entry.getLongValue());
      this.sumOfCounts += entry.getLongValue();
    }
  }

  // Exposed for testing
  void add(int bucket, long count)
  {
    if (bucket >= PercentileBuckets.length() || bucket < 0) {
      throw new IAE("Bucket index out of range (0, " + PercentileBuckets.length() + ")");
    }
    writableMap().addTo((short) bucket, count);
    this.sumOfCounts += count;
  }

  private void add(Object key, Number value)
  {
    if (key instanceof String) {
      this.add(Integer.parseInt((String) key), value.longValue());
      return;
    }
    if (Number.class.isAssignableFrom(key.getClass())) {
      this.add(((Number) key).intValue(), value.longValue());
      return;
    }
    throw new IAE(
        "Cannot add " + key.getClass() + "/" + value.getClass() + " to a Spectator Histogram"
    );

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Convert raw values to bucket indices with PercentileBuckets.indexOf(long value) before inserting.
  2. Validate serialized map keys are in [0, PercentileBuckets.length()) before passing them to deserialize/add.
  3. Use the public insert(Number) API instead of the package-private add(int, long) unless you already hold a valid bucket index.

Example fix

// before
histogram.add(rawValue, 1); // rawValue is a measurement, not a bucket index
// after
int bucket = PercentileBuckets.indexOf(rawValue);
histogram.add(bucket, 1);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidBucket(long idx) {
  return idx >= 0 && idx < PercentileBuckets.length();
}

Type guard

null

Try / catch

try {
  histogram.insert(value);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Bucket index out of range")) {
    throw new IAE("Value does not map to a valid percentile bucket", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling insert(value) with a numeric key whose intValue() is negative or >= PercentileBuckets.length(); calling package-private add(bucket, count) directly in tests with an out-of-range bucket; deserializing a map that contains keys outside the valid bucket range.

Common situations: Users feeding raw values (e.g. latencies in arbitrary units) instead of bucket indices via deserialize; a corrupted or hand-edited serialized histogram containing bad keys; test code guessing bucket ids instead of using PercentileBuckets.indexOf.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/0fcf6540649d61ae. Report an issue: GitHub.