{"record":{"id":"eaf8ab65cf4f1f27","repo":"apache/druid","slug":"bf1-numhashfunctions-numbits-does-not-match-bf2","errorCode":null,"errorMessage":"bf1 NumHashFunctions/NumBits does not match bf2","messagePattern":"bf1 NumHashFunctions/NumBits does not match bf2","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/filter/BloomKFilter.java","lineNumber":212,"sourceCode":"   * @param bf2Length\n   */\n  public static void mergeBloomFilterBytes(\n      byte[] bf1Bytes,\n      int bf1Start,\n      int bf1Length,\n      byte[] bf2Bytes,\n      int bf2Start,\n      int bf2Length\n  )\n  {\n    if (bf1Length != bf2Length) {\n      throw new IllegalArgumentException(\"bf1Length \" + bf1Length + \" does not match bf2Length \" + bf2Length);\n    }\n\n    // Validation on the bitset size/3 hash functions.\n    for (int idx = 0; idx < START_OF_SERIALIZED_LONGS; ++idx) {\n      if (bf1Bytes[bf1Start + idx] != bf2Bytes[bf2Start + idx]) {\n        throw new IllegalArgumentException(\"bf1 NumHashFunctions/NumBits does not match bf2\");\n      }\n    }\n\n    // Just bitwise-OR the bits together - size/# functions should be the same,\n    // rest of the data is serialized long values for the bitset which are supposed to be bitwise-ORed.\n    for (int idx = START_OF_SERIALIZED_LONGS; idx < bf1Length; ++idx) {\n      bf1Bytes[bf1Start + idx] |= bf2Bytes[bf2Start + idx];\n    }\n  }\n\n  public static void serialize(ByteBuffer out, BloomKFilter bloomFilter)\n  {\n    serialize(out, out.position(), bloomFilter);\n  }\n\n  /**\n   * Serialize a bloom filter to a ByteBuffer. Does not mutate buffer position.\n   *","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/filter/BloomKFilter.java#L194-L230","documentation":"mergeBloomFilterBytes() can only OR together two BloomKFilter bitsets built with identical parameters. After checking equal serialized lengths, it compares the header bytes (numHashFunctions and bitset size fields before the serialized longs) and throws when they differ — the faulty inputs are two bloom filters created with different numEntries/numHashFunctions (e.g. merged from aggregators configured with different numEntries, or one side is corrupted).","triggerScenarios":"Thrown at extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/filter/BloomKFilter.java:212 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure every bloom filter aggregator in the query uses the same numEntries setting so filters share identical hash-function count and bitset size","Check segment metadata for bloom filters produced with mismatched or corrupt parameters and rebuild affected segments","If filters come from different data sources or ingestion times with different configs, merge them only after rebuilding with a common configuration"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}