prestodb/presto · error · PrestoException
EXCEEDED_PLAN_NODE_LIMIT
EXCEEDED_PLAN_NODE_LIMIT
Error message
Number of leaf nodes in logical plan exceeds threshold %s set in max_leaf_nodes_in_plan
What it means
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.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/planner/SqlPlannerContext.java:61
this.cteInfo = new CteInfo();
}
public CteInfo getCteInfo()
{
return cteInfo;
}
public SqlToRowExpressionTranslator.Context getTranslatorContext()
{
return translatorContext;
}
public void incrementLeafNodes(Session session)
{
leafNodesInLogicalPlan += 1;
if (isLeafNodeLimitEnabled(session)) {
if (leafNodesInLogicalPlan > getMaxLeafNodesInPlan(session)) {
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",
getMaxLeafNodesInPlan(session)));
}
}
}
public class CteInfo
{
@VisibleForTesting
public static final String delimiter = "_*%$_";
// never decreases
private int prefix;
// Map a cte Query to a unique ID, which will be used in CTE reference node to identify the same CTE
private final Map<NodeRef<Query>, String> cteQueryUniqueIdMap = new HashMap<>();
public String normalize(NodeRef<Query> queryNodeRef, String cteName)
{
if (cteQueryUniqueIdMap.containsKey(queryNodeRef)) {View on GitHub (pinned to 55bb57d202)
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
Example fix
// before max_leaf_nodes_in_plan=100 // after max_leaf_nodes_in_plan=1000
Defensive patterns
Strategy: validation
Validate before calling
// Estimate leaves (referenced tables + VALUES) before submitting
long leaves = countTablesReferenced(sql) + countValuesClauses(sql);
long limit = getSessionProperty("max_leaf_nodes_in_plan");
if (leaves > limit) {
throw new IllegalStateException("Query references " + leaves + " leaf sources; limit is " + limit);
} Try / catch
try {
execute(sql);
} catch (PrestoException e) {
if (e.getErrorCode().getName().equals("EXCEEDED_PLAN_NODE_LIMIT")) {
throw new IllegalArgumentException("Reduce number of referenced tables or raise max_leaf_nodes_in_plan", e);
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- QUERY_HAS_TOO_MANY_STAGES
- NOT_SUPPORTED
- NODE_SELECTION_NOT_SUPPORTED
- INVALID_LIMIT_CLAUSE
- QUERY_PLANNING_TIMEOUT
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/04987deb6a62cdeb.
Report an issue: GitHub.