apache/druid · error · IAE
Cannot create bloom filter %s for invalid column type [%s]
Error message
Cannot create bloom filter %s for invalid column type [%s]
What it means
factorizeInternal() switches on the column capabilities (type) of the field being aggregated. Bloom filters can only aggregate string-like or complex bloom-filter columns; a column with an unsupported type (e.g. long/double/numeric) hits the default branch and throws this IllegalArgumentException naming the column type.
Source
Thrown at extensions-core/druid-bloom-filter/src/main/java/org/apache/druid/query/aggregation/bloom/BloomFilterAggregatorFactory.java:292
columnFactory.makeColumnValueSelector(field.getDimension()),
maxNumEntries,
onHeap
);
case DOUBLE:
return new DoubleBloomFilterAggregator(
columnFactory.makeColumnValueSelector(field.getDimension()),
maxNumEntries,
onHeap
);
case COMPLEX:
// in an ideal world, we would check complex type, but until then assume it's a bloom filter
return new BloomFilterMergeAggregator(
columnFactory.makeColumnValueSelector(field.getDimension()),
maxNumEntries,
onHeap
);
default:
throw new IAE(
"Cannot create bloom filter %s for invalid column type [%s]",
onHeap ? "aggregator" : "buffer aggregator",
capabilities.asTypeString()
);
}
} else {
// No column capabilities, try to guess based on selector type.
BaseNullableColumnValueSelector selector = columnFactory.makeColumnValueSelector(field.getDimension());
if (selector instanceof NilColumnValueSelector) {
return new NoopBloomFilterAggregator(maxNumEntries, onHeap);
} else if (selector instanceof DimensionSelector) {
return new StringBloomFilterAggregator((DimensionSelector) selector, maxNumEntries, onHeap);
} else {
// Use fallback 'object' aggregator.
return new ObjectBloomFilterAggregator(
columnFactory.makeColumnValueSelector(field.getDimension()),
maxNumEntries,View on GitHub (pinned to 9b90983fd2)
Solutions
- Aggregate a STRING-typed column: cast or add a transform/expression in the query, e.g. use "type": "default" dimension with an expression like CAST(col AS STRING) via an ExpressionDimensionSpec
- Fix ingestion to store the column as string if bloom filtering on it is required
- Verify the dimension name points to the intended column and check its type via segment metadata query
- Use the SQL layer with BLOOM_FILTER_AGG and CAST(col, 'VARCHAR')
Example fix
// before
{"type": "bloom", "name": "bf", "field": {"type": "default", "dimension": "user_id_long"}} // numeric column
// after
{"type": "bloom", "name": "bf", "field": {"type": "expression", "expression": "CAST(user_id_long AS VARCHAR)", "dimension": "user_id_str"}} Defensive patterns
Strategy: validation
Validate before calling
// Check column type before running the bloom aggregation (segment metadata query) // SELECT column, dataType FROM sys.segments ... or use SegmentMetadataQuery; require VALUE_TYPE_STRING boolean ok = "STRING".equals(capabilities.getType().toString());
Try / catch
try {
aggregator = factory.factorize(selectorFactory);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("invalid column type")) {
// re-plan query with a cast/expression dimension to STRING
} else throw e;
} Prevention
- Run a SegmentMetadataQuery (or SQL 'SELECT "dataType" FROM information_schema.columns') to confirm the column is STRING before bloom aggregation
- CAST numeric columns to VARCHAR (expression dimension) when needed
- Verify dimension names to avoid resolving to wrong-typed columns
When it happens
Trigger: Running a query with a 'bloom' aggregator on a dimension whose underlying column type is not STRING (or the bloom-filter complex type), e.g. aggregating a numeric (long/double/float) column or a schemaless/mismatched column; calling factorize()/factorizeBuffered() on a ColumnSelectorFactory whose capabilities.asTypeString() reports VALUE_TYPE_NUMERIC or similar.
Common situations: Querying a numeric metric column with a bloom aggregator by mistake; schema evolved so the column is now numeric; typo'd dimension resolving to the wrong column; schemaless ingestion auto-detected numbers where strings were expected.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Emit called unexpectedly before service start
- Got an exception while parsing file [%s]
- Unable to copy key [%s] to file [%s]
- unknown event type [%s]
- interrupted flushing elements from queue
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/58eac01422921a29.
Report an issue: GitHub.