apache/druid · error · IllegalArgumentException

BloomKFilters are not compatible for merging. this

Error message

BloomKFilters are not compatible for merging. this - %s that - %s

What it means

BloomKFilter.merge() only combines two filters built with identical bit-size (m) and hash-function count (k). If either parameter differs — or the filter is merged with itself through a wrong reference check path — the merge is rejected with this IllegalArgumentException, because the resulting bitset would be meaningless.

Solutions

  1. Check compatibility first: verify both filters expose the same m and k (use BloomKFilterHolder fields or the string from the exception) before merging.
  2. Standardize the numEntries (and fpp) parameter for the query/inclusion so all filters are built with identical size and hash count.
  3. Rebuild the offending filter(s) with the same parameters as the target filter, then retry the merge.

Example fix

// before
BloomKFilter merged = new BloomKFilter(numRows); // task-specific
merged.merge(otherFilter); // may throw

// after
if (otherFilter != null && isCompatible(merged, otherFilter)) {
  merged.merge(otherFilter);
} else {
  throw new ISE("Incompatible bloom filter: %s", otherFilter);
}
Defensive patterns

Strategy: validation

Validate before calling

// Java: check m and k before merging
public static boolean canMerge(BloomKFilter a, BloomKFilter b) {
  return a != null && b != null && a.getBitSize() == b.getBitSize() && a.getNumHashes() == b.getNumHashes();
}

Try / catch

try {
  target.merge(that);
} catch (IllegalArgumentException e) {
  // log filter parameters from e.getMessage() and rebuild with matched m/k
}

Prevention

When it happens

Trigger: Calling bloomFilter.merge(other) where other was constructed with a different expected number of items (different m), a different numEntries/fpp yielding different k, or deserialized from data produced with different parameters.

Common situations: Merging bloom filters computed in different ingestion tasks with different numEntries settings; loading serialized filters from older data versions; aggregating filters across segments where per-segment parameters were auto-computed from different row counts.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/filter/BloomKFilter.java:707

  }

  @Override
  public String toString()
  {
    return "m: " + m + " k: " + k;
  }

  /**
   * Merge the specified bloom filter with current bloom filter.
   *
   * @param that - bloom filter to merge
   */
  public void merge(BloomKFilter that)
  {
    if (this != that && this.m == that.m && this.k == that.k) {
      this.bitSet.putAll(that.bitSet);
    } else {
      throw new IllegalArgumentException("BloomKFilters are not compatible for merging." +
                                         " this - " + this + " that - " + that);
    }
  }

  public void reset()
  {
    this.bitSet.clear();
  }

  /**
   * Bare metal bit set implementation. For performance reasons, this implementation does not check
   * for index bounds nor expand the bit set size if the specified index is greater than the size.
   */
  public static class BitSet
  {
    private final long[] data;

    public BitSet(long bits)

View on GitHub (pinned to 9b90983fd2)