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

  1. Raise the limit: set max_leaf_nodes_in_plan config property or the corresponding session property higher
  2. Rewrite the query to reference fewer leaf sources (consolidate tables, use partition filters, or materialize intermediate results)
  3. Split the mega-query into several smaller queries writing to staging tables
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/04987deb6a62cdeb. Report an issue: GitHub.