apache/druid · error · ISE

Unexpected NilColumnValueSelector

Error message

Unexpected NilColumnValueSelector

What it means

BloomFilterMergeAggregatorFactory.makeMergeAggregator() asserts that the selector for the field is not a NilColumnValueSelector (a selector that always returns null, e.g. for nonexistent columns). Since merge inputs should always carry serialized bloom filter values as empty filters rather than nulls, a nil selector violates the contract and throws IllegalStateException.

Solutions

  1. Fix the merge aggregator's fieldName to match the output column actually produced by the upstream bloom aggregation
  2. Ensure all segments/subqueries produce the bloom filter column (use default empty-filter output for missing data)
  3. Add exists-checks / use segment metadata to confirm column presence before merging
  4. Align schemas across segments so the bloom column is never absent

Example fix

// before
{"type": "bloomMerge", "name": "bf", "fieldName": "bf_out"} // bf_out missing from one subquery result
// after
{"type": "query", "query": {"queryType": "groupBy", "aggregations": [{"type": "bloom", "name": "bf_out", ...}]}}
// then merge with matching fieldName "bf_out" (verified present in every subquery result)
Defensive patterns

Strategy: validation

Validate before calling

// Verify the merge field exists in all result sets before merging
// e.g. inspect the subquery/broker result's column list for fieldName
boolean fieldPresent = resultColumns.contains(mergeFactory.getFieldName());

Type guard

if (selector instanceof NilColumnValueSelector) { /* handle missing column: error or empty filter */ }

Try / catch

try {
  aggregator = mergeFactory.factorize(metricFactory);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("Unexpected NilColumnValueSelector")) {
    // correct fieldName or add missing column upstream
  } else throw e;
}

Prevention

When it happens

Trigger: Calling factorize/factorizeBuffered on a BloomFilterMergeAggregatorFactory where the requested field name does not exist in the segment/result columns (Druid returns a nil selector), e.g. merging results where one side lacks the bloom column, or a typo'd field name in the merge aggregator spec.

Common situations: Broker-side merge of group-by/subquery results where a shard has no matching column; schema drift between segments; misconfigured merge aggregator 'fieldName' pointing to a non-existent output column.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/aggregation/bloom/BloomFilterMergeAggregatorFactory.java:77

  {
    return new CacheKeyBuilder(AggregatorUtil.BLOOM_FILTER_MERGE_CACHE_TYPE_ID)
        .appendString(fieldName)
        .appendInt(getMaxNumEntries())
        .build();
  }

  @Override
  public AggregatorFactory withName(String newName)
  {
    return new BloomFilterMergeAggregatorFactory(newName, fieldName, getMaxNumEntries());
  }

  private BloomFilterMergeAggregator makeMergeAggregator(ColumnSelectorFactory metricFactory)
  {
    final BaseNullableColumnValueSelector selector = metricFactory.makeColumnValueSelector(fieldName);
    // null columns should be empty bloom filters by this point, so encountering a nil column in merge agg is unexpected
    if (selector instanceof NilColumnValueSelector) {
      throw new ISE("Unexpected NilColumnValueSelector");
    }
    return new BloomFilterMergeAggregator((ColumnValueSelector<ByteBuffer>) selector, getMaxNumEntries(), true);
  }
}

View on GitHub (pinned to 9b90983fd2)