apache/hadoop · error · IllegalArgumentException

filters cannot be xor-ed

Error message

filters cannot be xor-ed

What it means

BloomFilter.xor(Filter) symmetric-differences another filter's bits into this one and enforces the same compatibility rule as and()/or(): the operand must be a non-null BloomFilter with identical vectorSize and nbHash. Because xor mixes bit patterns, shape mismatch would corrupt the filter's semantics, so it fails with IllegalArgumentException('filters cannot be xor-ed') rather than producing garbage.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/bloom/BloomFilter.java:180

  @Override
  public void or(Filter filter) {
    if(filter == null
        || !(filter instanceof BloomFilter)
        || filter.vectorSize != this.vectorSize
        || filter.nbHash != this.nbHash) {
      throw new IllegalArgumentException("filters cannot be or-ed");
    }
    bits.or(((BloomFilter) filter).bits);
  }

  @Override
  public void xor(Filter filter) {
    if(filter == null
        || !(filter instanceof BloomFilter)
        || filter.vectorSize != this.vectorSize
        || filter.nbHash != this.nbHash) {
      throw new IllegalArgumentException("filters cannot be xor-ed");
    }
    bits.xor(((BloomFilter) filter).bits);
  }

  @Override
  public String toString() {
    return bits.toString();
  }

  /**
   * @return size of the the bloomfilter
   */
  public int getVectorSize() {
    return this.vectorSize;
  }

  // Writable

View on GitHub (pinned to 2add963021)

Solutions

  1. Ensure both filters share vectorSize and nbHash by constructing them from the same parameters.
  2. If one filter came from serialized storage, compare its getVectorSize()/nbHash with the local one before xor.
  3. Rebuild the older filter from source data with current parameters instead of xoring mismatched shapes.
  4. Wrap xor in a shape check and fail with a descriptive error including both sizes.

Example fix

// before
a.xor(b); // b built with vectorSize 512 vs a's 1024
// throws: filters cannot be xor-ed

// after
if (b.vectorSize == a.vectorSize && b.nbHash == a.nbHash) {
  a.xor(b);
} else {
  throw new IllegalStateException("filter shape mismatch: rebuild snapshot");
}
Defensive patterns

Strategy: validation

Validate before calling

if (b != null && b.vectorSize == a.vectorSize && b.nbHash == a.nbHash) {
  a.xor(b);
} else {
  throw new IllegalStateException(
      "Cannot xor filters of different shapes; rebuild snapshots");
}

Type guard

static boolean xorCompatible(BloomFilter a, BloomFilter b) {
  return b != null && b.vectorSize == a.vectorSize && b.nbHash == a.nbHash;
}

Prevention

When it happens

Trigger: filterA.xor(filterB) across filters built with different vectorSize/nbHash; filterA.xor(null); passing a Filter-typed object of another concrete class.

Common situations: Diff-style computations (what changed between two snapshots) where one snapshot's filter was created earlier with different settings; filters deserialized from stores written with different versions/configs.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/d10965b6af7fb250. Report an issue: GitHub.