prestodb/presto · error · SemanticException
NESTED_WINDOW
NESTED_WINDOW
Error message
Cannot nest window functions inside aggregation '%s': %s
What it means
AggregationAnalyzer.visitFunctionCall rejects window functions (OVER ...) nested inside an aggregate function's arguments. Window functions are computed after aggregation, so appearing inside an aggregate argument is invalid; throws NESTED_WINDOW with the outer aggregate name and inner window calls.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/AggregationAnalyzer.java:404
}
}
if (!node.getWindow().isPresent()) {
List<FunctionCall> aggregateFunctions = extractAggregateFunctions(
analysis.getFunctionHandles(),
node.getArguments(),
functionAndTypeResolver);
List<FunctionCall> windowFunctions = extractWindowFunctions(node.getArguments());
if (!aggregateFunctions.isEmpty()) {
throw new SemanticException(NESTED_AGGREGATION,
node,
"Cannot nest aggregations inside aggregation '%s': %s",
node.getName(),
aggregateFunctions);
}
if (!windowFunctions.isEmpty()) {
throw new SemanticException(NESTED_WINDOW,
node,
"Cannot nest window functions inside aggregation '%s': %s",
node.getName(),
windowFunctions);
}
if (node.getOrderBy().isPresent()) {
List<Expression> sortKeys = node.getOrderBy().get().getSortItems().stream()
.map(SortItem::getSortKey)
.collect(toImmutableList());
if (node.isDistinct()) {
List<FieldId> fieldIds = node.getArguments().stream()
.map(NodeRef::of)
.map(columnReferences::get)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(toImmutableList());
for (Expression sortKey : sortKeys) {View on GitHub (pinned to 55bb57d202)
Solutions
- Compute the window function in a subquery/CTE first, then aggregate its result in the outer query
- If you wanted a window over an aggregate, apply the aggregate in GROUP BY and then OVER () on the aggregated value in an outer SELECT
- Remove the OVER clause if the inner function was meant to be a plain aggregate argument
Example fix
// before SELECT sum(row_number() OVER (ORDER BY order_date)) FROM orders // after SELECT sum(rn) FROM (SELECT row_number() OVER (ORDER BY order_date) AS rn FROM orders) t
Defensive patterns
Strategy: validation
Validate before calling
// reject window functions inside aggregate arguments before executing
boolean windowInsideAggregate = containsWindowFunctionInsideAggregateCall(expression); // AST walk
if (windowInsideAggregate) throw new IllegalArgumentException("window function inside aggregate"); Try / catch
catch (SemanticException e) { if (e.getCode() == NESTED_WINDOW) { /* hoist window into subquery, aggregate outside */ } throw e; } Prevention
- Remember window functions evaluate after aggregation; never nest them inside aggregates
- Use subqueries/CTEs to layer window and aggregate computations
- Lint SQL for OVER(...) appearing inside aggregate parentheses
- Cover window+aggregate combinations in query tests
When it happens
Trigger: Queries like sum(row_number() OVER (PARTITION BY x ORDER BY y)) or count(sum(x) OVER ()), where extractWindowFunctions finds window FunctionCalls among the aggregate's arguments.
Common situations: Attempting to total a running/ranking value; misreading evaluation order of window vs aggregate functions; generated SQL wrapping aggregates around analytic expressions.
Related errors
- MUST_BE_AGGREGATE_OR_GROUP_BY
- NESTED_AGGREGATION
- MUST_BE_AGGREGATION_FUNCTION
- ORDER_BY_MUST_BE_IN_AGGREGATE
- MISSING_ORDER_BY
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/c126547acccbe301.
Report an issue: GitHub.