{"record":{"id":"0fcf6540649d61ae","repo":"apache/druid","slug":"bucket-index-out-of-range-0","errorCode":null,"errorMessage":"Bucket index out of range (0, )","messagePattern":"Bucket index out of range \\(0, \\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogram.java","lineNumber":305,"sourceCode":"  }\n\n  void merge(SpectatorHistogram source)\n  {\n    if (source == null) {\n      return;\n    }\n    Short2LongOpenHashMap writableMap = writableMap();\n    for (Short2LongMap.Entry entry : Short2LongMaps.fastIterable(source.readableMap())) {\n      writableMap.addTo(entry.getShortKey(), entry.getLongValue());\n      this.sumOfCounts += entry.getLongValue();\n    }\n  }\n\n  // Exposed for testing\n  void add(int bucket, long count)\n  {\n    if (bucket >= PercentileBuckets.length() || bucket < 0) {\n      throw new IAE(\"Bucket index out of range (0, \" + PercentileBuckets.length() + \")\");\n    }\n    writableMap().addTo((short) bucket, count);\n    this.sumOfCounts += count;\n  }\n\n  private void add(Object key, Number value)\n  {\n    if (key instanceof String) {\n      this.add(Integer.parseInt((String) key), value.longValue());\n      return;\n    }\n    if (Number.class.isAssignableFrom(key.getClass())) {\n      this.add(((Number) key).intValue(), value.longValue());\n      return;\n    }\n    throw new IAE(\n        \"Cannot add \" + key.getClass() + \"/\" + value.getClass() + \" to a Spectator Histogram\"\n    );","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogram.java#L287-L323","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Convert raw values to bucket indices with PercentileBuckets.indexOf(long value) before inserting.","Validate serialized map keys are in [0, PercentileBuckets.length()) before passing them to deserialize/add.","Use the public insert(Number) API instead of the package-private add(int, long) unless you already hold a valid bucket index."],"exampleFix":"// before\nhistogram.add(rawValue, 1); // rawValue is a measurement, not a bucket index\n// after\nint bucket = PercentileBuckets.indexOf(rawValue);\nhistogram.add(bucket, 1);","handlingStrategy":"validation","validationCode":"static boolean isValidBucket(long idx) {\n  return idx >= 0 && idx < PercentileBuckets.length();\n}","typeGuard":"null","tryCatchPattern":"try {\n  histogram.insert(value);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Bucket index out of range\")) {\n    throw new IAE(\"Value does not map to a valid percentile bucket\", e);\n  }\n  throw e;\n}","preventionTips":["Always convert raw measurements via PercentileBuckets.indexOf before bucket-level calls.","Use the public insert(Number) API rather than the package-private add(int, long).","Validate keys of maps destined for deserialize against PercentileBuckets.length()."],"tags":["index-out-of-range","illegal-argument"],"backgroundTag":"index-out-of-bounds","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}