apache/druid · error · CNFFilterExplosionException
Exceeded maximum allowed filters for CNF (conjunctive…
Error message
Exceeded maximum allowed filters for CNF (conjunctive normal form) conversion
What it means
HiveCnfHelper.convertToCnfWithLimit throws CNFFilterExplosionException when converting a filter's AND branch to CNF would exceed maxCNFFilterLimit (the budget of filters allowed after expansion). CNF conversion of nested boolean filters can blow up combinatorially, so Druid bounds it. This prevents query planning from consuming unbounded memory/time.
Solutions
- Simplify the boolean filter expression before conversion (flatten redundant AND/OR nesting)
- Increase the max CNF filter limit configuration if appropriate for your workload
- Split the query into smaller queries with fewer boolean conditions
Example fix
// before Filters.toCnf(hugeNestedFilter, 50); // exceeds limit of 50 // after Filter simplified = Filters.flatten(hugeNestedFilter); Filters.toCnf(simplified, 1000); // raised limit + simplified tree
Defensive patterns
Strategy: try-catch
Validate before calling
int estimated = estimateCnfSize(filter); if (estimated > maxCnfFilterLimit) { /* simplify or split first */ } Try / catch
try { cnf = Filters.toCnf(filter, limit); } catch (CNFFilterExplosionException e) { cnf = filter; /* fall back to unconverted filter */ } Prevention
- Prefer IN filters over long OR chains
- Keep boolean filter nesting shallow
- Tune the CNF limit for your query workload
When it happens
Trigger: Running Filters.toCnf (or query translation that uses it) on an AndFilter whose subtree, once recursively converted, would produce more than the configured CNF filter limit.
Common situations: Queries with large OR-of-AND expressions (many disjunctive predicates); nested boolean expressions from generated SQL; low server-side CNF limit settings.
Related errors
- Received a non-applicable rewrite
- Received a non-applicable rewrite
- 08001
- A batch appenderator was already created for this peon's…
- A-Not-B requires at least 1 sketch
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/cae4db0f17ef67b0.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/filter/cnf/HiveCnfHelper.java:111
* @throws CNFFilterExplosionException is thrown if the filters in CNF representation go beyond maxCNFFilterLimit
*/
private static NonnullPair<Filter, Integer> convertToCnfWithLimit(
Filter current,
int maxCNFFilterLimit
) throws CNFFilterExplosionException
{
if (current instanceof NotFilter) {
NonnullPair<Filter, Integer> result = convertToCnfWithLimit(((NotFilter) current).getBaseFilter(), maxCNFFilterLimit);
return new NonnullPair<>(new NotFilter(result.lhs), result.rhs);
}
if (current instanceof AndFilter) {
List<Filter> children = new ArrayList<>();
for (Filter child : ((AndFilter) current).getFilters()) {
NonnullPair<Filter, Integer> result = convertToCnfWithLimit(child, maxCNFFilterLimit);
children.add(result.lhs);
maxCNFFilterLimit = result.rhs;
if (maxCNFFilterLimit < 0) {
throw new CNFFilterExplosionException("Exceeded maximum allowed filters for CNF (conjunctive normal form) conversion");
}
}
return new NonnullPair<>(Filters.and(children), maxCNFFilterLimit);
}
if (current instanceof OrFilter) {
// a list of leaves that weren't under AND expressions
List<Filter> nonAndList = new ArrayList<>();
// a list of AND expressions that we need to distribute
List<Filter> andList = new ArrayList<>();
for (Filter child : ((OrFilter) current).getFilters()) {
if (child instanceof AndFilter) {
andList.add(child);
} else if (child instanceof OrFilter) {
// pull apart the kids of the OR expression
nonAndList.addAll(((OrFilter) child).getFilters());
} else {
nonAndList.add(child);
}View on GitHub (pinned to 9b90983fd2)