You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AQE: handle executor failure on the adaptive execution path #1986
Is your feature request related to a problem or challenge?
The adaptive execution path (AdaptiveExecutionGraph / AdaptivePlanner) currently covers the happy path only and "does not cover executor failure". When AQE is enabled, the scheduler builds the stage DAG incrementally and re-optimizes the remaining plan as each shuffle stage completes. If an executor is lost, the runtime statistics and shuffle output that adaptive decisions were based on may no longer be available, and the AQE path has no recovery logic equivalent to the static StaticExecutionGraph path.
Describe the solution you'd like
Support executor-failure recovery on the AQE path: detect lost shuffle output for stages the adaptive planner has already resolved/consumed, re-run the affected stage(s), and re-drive adaptive re-optimization consistently after recovery.
Additional context
Related general failure-handling issues (not AQE-path specific): #1795, #1908.
Context
This is one of the documented limitations of the experimental Adaptive Query Execution (AQE) path, listed in docs/source/user-guide/tuning-guide.md under "Current limitations" and in the doc comment on AdaptiveExecutionGraph (ballista/scheduler/src/state/aqe/mod.rs). Filing a discrete tracking issue so the gap is visible outside the doc.
Some specifics from reading AdaptiveExecutionGraph::update_task_status side by side with the static graph, at commit ea1126c, that are relevant here:
The reset-running-stages path is dead code on the AQE graph.reset_running_stages is declared as an immutable empty map (aqe/mod.rs#L817), so the reset loop at L1106-L1130 never runs and the !reset_running_stages.contains_key(&stage_id) check at L1013 is always true. In the static graph the same map is mut and is populated by the late fetch-failure handling.
The late fetch-failure path for UnResolved stages is missing.StaticExecutionGraph::update_task_status handles fetch failures reported for stages that are still UnResolved (execution_graph.rs#L1016-L1088); the AQE copy has no equivalent, which is the main source of the dead code above.
The max-task-failures message is less useful on AQE. The AQE copy reports only the internal task slot id (aqe/mod.rs#L942-L948), while the static copy reports the partitions that exceeded the limit (execution_graph.rs#L910-L937).
These are all consequences of the two update_task_status implementations being separate copies. #2595 tracks sharing the execution-graph code between the static and adaptive graphs, which would let the recovery logic here be implemented once. A related AQE-only bug where a stage is dropped from the graph on a failed conversion is #2594.
Activity
andygrove commentedon Oct 14, 2026
Some specifics from reading
AdaptiveExecutionGraph::update_task_statusside by side with the static graph, at commit ea1126c, that are relevant here:reset_running_stagesis declared as an immutable empty map (aqe/mod.rs#L817), so the reset loop at L1106-L1130 never runs and the!reset_running_stages.contains_key(&stage_id)check at L1013 is always true. In the static graph the same map ismutand is populated by the late fetch-failure handling.StaticExecutionGraph::update_task_statushandles fetch failures reported for stages that are still UnResolved (execution_graph.rs#L1016-L1088); the AQE copy has no equivalent, which is the main source of the dead code above.These are all consequences of the two
update_task_statusimplementations being separate copies. #2595 tracks sharing the execution-graph code between the static and adaptive graphs, which would let the recovery logic here be implemented once. A related AQE-only bug where a stage is dropped from the graph on a failed conversion is #2594.