{"record":{"id":"04987deb6a62cdeb","repo":"prestodb/presto","slug":"exceeded-plan-node-limit","errorCode":"EXCEEDED_PLAN_NODE_LIMIT","errorMessage":"Number of leaf nodes in logical plan exceeds threshold %s set in max_leaf_nodes_in_plan","messagePattern":"Number of leaf nodes in logical plan exceeds threshold (.+?) set in max_leaf_nodes_in_plan","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/planner/SqlPlannerContext.java","lineNumber":61,"sourceCode":"        this.cteInfo = new CteInfo();\n    }\n\n    public CteInfo getCteInfo()\n    {\n        return cteInfo;\n    }\n\n    public SqlToRowExpressionTranslator.Context getTranslatorContext()\n    {\n        return translatorContext;\n    }\n\n    public void incrementLeafNodes(Session session)\n    {\n        leafNodesInLogicalPlan += 1;\n        if (isLeafNodeLimitEnabled(session)) {\n            if (leafNodesInLogicalPlan > getMaxLeafNodesInPlan(session)) {\n                throw new PrestoException(EXCEEDED_PLAN_NODE_LIMIT, format(\"Number of leaf nodes in logical plan exceeds threshold %s set in max_leaf_nodes_in_plan\",\n                        getMaxLeafNodesInPlan(session)));\n            }\n        }\n    }\n\n    public class CteInfo\n    {\n        @VisibleForTesting\n        public static final String delimiter = \"_*%$_\";\n        // never decreases\n        private int prefix;\n\n        // Map a cte Query to a unique ID, which will be used in CTE reference node to identify the same CTE\n        private final Map<NodeRef<Query>, String> cteQueryUniqueIdMap = new HashMap<>();\n\n        public String normalize(NodeRef<Query> queryNodeRef, String cteName)\n        {\n            if (cteQueryUniqueIdMap.containsKey(queryNodeRef)) {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/planner/SqlPlannerContext.java#L43-L79","documentation":"SqlPlannerContext tracks the number of leaf nodes (table scans, VALUES) in the logical plan and enforces the session/config limit max_leaf_nodes_in_plan. Each incrementLeafNodes call from visitTable or visitValues checks the running count; exceeding the configured threshold throws EXCEEDED_PLAN_NODE_LIMIT to protect the coordinator from unmanageably large plans.","triggerScenarios":"A query referencing more table scans/VALUES clauses than the configured max_leaf_nodes_in_plan limit — e.g. very large UNION ALL of hundreds of tables, or generated SQL touching many tables/schemas.","commonSituations":"Data-discovery or federated queries hitting dozens/hundreds of external tables; auto-generated ETL SQL enumerating many tables; low limit configured (max_leaf_nodes_in_plan) in coordinator config.","solutions":["Raise the limit: set max_leaf_nodes_in_plan config property or the corresponding session property higher","Rewrite the query to reference fewer leaf sources (consolidate tables, use partition filters, or materialize intermediate results)","Split the mega-query into several smaller queries writing to staging tables","If the limit was disabled intentionally, ensure isLeafNodeLimitEnabled(session) is false via config"],"exampleFix":"// before\nmax_leaf_nodes_in_plan=100\n// after\nmax_leaf_nodes_in_plan=1000","handlingStrategy":"validation","validationCode":"// Estimate leaves (referenced tables + VALUES) before submitting\nlong leaves = countTablesReferenced(sql) + countValuesClauses(sql);\nlong limit = getSessionProperty(\"max_leaf_nodes_in_plan\");\nif (leaves > limit) {\n    throw new IllegalStateException(\"Query references \" + leaves + \" leaf sources; limit is \" + limit);\n}","typeGuard":null,"tryCatchPattern":"try {\n    execute(sql);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getName().equals(\"EXCEEDED_PLAN_NODE_LIMIT\")) {\n        throw new IllegalArgumentException(\"Reduce number of referenced tables or raise max_leaf_nodes_in_plan\", e);\n    }\n    throw e;\n}","preventionTips":["Limit the number of tables in a single query; batch federated lookups","Materialize large unions of sources into a staging table","Configure max_leaf_nodes_in_plan appropriately for your workload","Filter to needed partitions instead of scanning every table"],"tags":["presto","planner","plan-limits","query-complexity"],"backgroundTag":"plan-node-limit-exceeded","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}