apache/druid · error · IllegalArgumentException

Index[%d] >= size[%d]

Error message

Index[%d] >= size[%d]

What it means

Bounds-check guard replicating Guava's Preconditions.checkElementIndex behavior for GenericIndexed: callers attempt to read element at 'index' and this fires when index >= the number of elements stored in the index, meaning the reader requested an element beyond what was serialized into the file. It indicates an out-of-range lookup into a file-backed GenericIndexed, typically from corrupt metadata, a stale dictionary reference, or an off-by-one caller; keep index within 0..size-1.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/data/GenericIndexed.java:498

      inspector.visit("strategy", strategy);
    }
  }

  /**
   * Checks  if {@code index} a valid `element index` in GenericIndexed.
   * Similar to Preconditions.checkElementIndex() except this method throws {@link IAE} with custom error message.
   * <p>
   * Used here to get existing behavior(same error message and exception) of V1 GenericIndexed.
   *
   * @param index index identifying an element of an GenericIndexed.
   */
  protected void checkIndex(int index)
  {
    if (index < 0) {
      throw new IAE("Index[%s] < 0", index);
    }
    if (index >= size) {
      throw new IAE("Index[%d] >= size[%d]", index, size);
    }
  }

  public Class<? extends T> getClazz()
  {
    return strategy.getClazz();
  }

  @Override
  public int size()
  {
    return size;
  }

  /**
   * Returns the index of "value" in this GenericIndexed object, or (-(insertion point) - 1) if the value is not
   * present, in the manner of Arrays.binarySearch. This strengthens the contract of Indexed, which only guarantees
   * that values-not-found will return some negative number.

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Bound loops with strict < size(), using indexed.size() rather than cached numbers.
  2. Guard reads: if (index >= indexed.size()) return null or throw a controlled error.
  3. Refresh any persisted cardinality/size values so they match the current segment.

Example fix

// before
for (int i = 0; i <= indexed.size(); i++) use(indexed.get(i));
// after
for (int i = 0; i < indexed.size(); i++) use(indexed.get(i));
Defensive patterns

Strategy: type-guard

Validate before calling

if (index >= indexed.size()) throw new IndexOutOfBoundsException("index " + index + " >= " + indexed.size());

Type guard

boolean inBounds(Indexed<?> idx, int i) { return i >= 0 && i < idx.size(); }

Try / catch

try { return indexed.get(i); } catch (IAE e) { log.warn("stale size metadata?", e); return null; }

Prevention

When it happens

Trigger: Calling get(index) with index >= the number of elements in the GenericIndexed, e.g. iterating with an off-by-one bound (<= size) or using stale size metadata.

Common situations: Loops like for (i = 0; i <= dim.size(); i++), cached/stale cardinality metadata after segment replacement, or external code assuming a larger dictionary.

Related errors


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