{"record":{"id":"cae4db0f17ef67b0","repo":"apache/druid","slug":"exceeded-maximum-allowed-filters-for-cnf-conjunct","errorCode":null,"errorMessage":"Exceeded maximum allowed filters for CNF (conjunctive normal form) conversion","messagePattern":"Exceeded maximum allowed filters for CNF \\(conjunctive normal form\\) conversion","errorType":"exception","errorClass":"CNFFilterExplosionException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/filter/cnf/HiveCnfHelper.java","lineNumber":111,"sourceCode":"   * @throws CNFFilterExplosionException is thrown if the filters in CNF representation go beyond maxCNFFilterLimit\n   */\n  private static NonnullPair<Filter, Integer> convertToCnfWithLimit(\n      Filter current,\n      int maxCNFFilterLimit\n  ) throws CNFFilterExplosionException\n  {\n    if (current instanceof NotFilter) {\n      NonnullPair<Filter, Integer> result = convertToCnfWithLimit(((NotFilter) current).getBaseFilter(), maxCNFFilterLimit);\n      return new NonnullPair<>(new NotFilter(result.lhs), result.rhs);\n    }\n    if (current instanceof AndFilter) {\n      List<Filter> children = new ArrayList<>();\n      for (Filter child : ((AndFilter) current).getFilters()) {\n        NonnullPair<Filter, Integer> result = convertToCnfWithLimit(child, maxCNFFilterLimit);\n        children.add(result.lhs);\n        maxCNFFilterLimit = result.rhs;\n        if (maxCNFFilterLimit < 0) {\n          throw new CNFFilterExplosionException(\"Exceeded maximum allowed filters for CNF (conjunctive normal form) conversion\");\n        }\n      }\n      return new NonnullPair<>(Filters.and(children), maxCNFFilterLimit);\n    }\n    if (current instanceof OrFilter) {\n      // a list of leaves that weren't under AND expressions\n      List<Filter> nonAndList = new ArrayList<>();\n      // a list of AND expressions that we need to distribute\n      List<Filter> andList = new ArrayList<>();\n      for (Filter child : ((OrFilter) current).getFilters()) {\n        if (child instanceof AndFilter) {\n          andList.add(child);\n        } else if (child instanceof OrFilter) {\n          // pull apart the kids of the OR expression\n          nonAndList.addAll(((OrFilter) child).getFilters());\n        } else {\n          nonAndList.add(child);\n        }","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/filter/cnf/HiveCnfHelper.java#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"Queries with large OR-of-AND expressions (many disjunctive predicates); nested boolean expressions from generated SQL; low server-side CNF limit settings.","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"],"exampleFix":"// before\nFilters.toCnf(hugeNestedFilter, 50); // exceeds limit of 50\n// after\nFilter simplified = Filters.flatten(hugeNestedFilter);\nFilters.toCnf(simplified, 1000); // raised limit + simplified tree","handlingStrategy":"try-catch","validationCode":"int estimated = estimateCnfSize(filter); if (estimated > maxCnfFilterLimit) { /* simplify or split first */ }","typeGuard":null,"tryCatchPattern":"try { cnf = Filters.toCnf(filter, limit); } catch (CNFFilterExplosionException e) { cnf = filter; /* fall back to unconverted filter */ }","preventionTips":["Prefer IN filters over long OR chains","Keep boolean filter nesting shallow","Tune the CNF limit for your query workload"],"tags":["java","filter","cnf","limit-exceeded"],"backgroundTag":"filter-conversion-limit-exceeded","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}