Skip to content

bug: Prevent exec hang when task decode fails#2016

Open
coderfender wants to merge 4 commits into
apache:mainfrom
coderfender:prevent_exec_hang_when_task_decode_fails
Open

bug: Prevent exec hang when task decode fails#2016
coderfender wants to merge 4 commits into
apache:mainfrom
coderfender:prevent_exec_hang_when_task_decode_fails

Conversation

@coderfender

@coderfender coderfender commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Closes #1908

Rationale for this change

What changes are included in this PR?

Previously, all errors were masked in a blanket error but we now handle task serialization / gRPC errors in a separate path and send an event to fail the corresponding job without marking the executor as dead essentially failing the query. This should help with cluster stability and determinism with regards to task serialization errors

Are there any user-facing changes?

@coderfender
coderfender marked this pull request as ready for review July 13, 2026 01:28
@github-actions github-actions Bot removed the python label Jul 13, 2026
@andygrove

Copy link
Copy Markdown
Member

Thanks @coderfender. The changes look reasonable, but is it possible to add tests to prevent regressions?

@coderfender
coderfender force-pushed the prevent_exec_hang_when_task_decode_fails branch from bb128bc to 04bb5e2 Compare July 13, 2026 21:57
@github-actions github-actions Bot added documentation Improvements or additions to documentation development-process labels Jul 13, 2026
@coderfender
coderfender force-pushed the prevent_exec_hang_when_task_decode_fails branch from 3687a9b to 9a1c33b Compare July 13, 2026 22:30
@github-actions github-actions Bot removed documentation Improvements or additions to documentation python development-process labels Jul 13, 2026
@coderfender

Copy link
Copy Markdown
Contributor Author

Added tests

@@ -258,7 +274,7 @@ impl<T: 'static + AsLogicalPlan, U: 'static + AsExecutionPlan> SchedulerState<T,
async fn launch_tasks(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

launch_tasks can combine stages from multiple jobs into one executor RPC, and then would now treat any InvalidArgument as a failure for every job in that RPC. The executor will process each job sequentially and then fail the first one with invalid argument:

ballista/executor/src/executor_server.rs:L850

   for multi_task in multi_tasks {
       let multi_task: Vec<TaskDefinition> = get_task_definition_vec(
           multi_task,
           // ...
       )
       .map_err(|e| Status::invalid_argument(format!("{e}")))?;

       for task in multi_task {
           task_sender
               .send(CuratorTaskDefinition {
                   scheduler_id: scheduler_id.clone(),
                   task,
               })
               .await
               .unwrap();
       }
   }

So this could cause tasks that were processed before the failing one to have already been enqueued, while skipping any tasks after the bad one. Then this code would mark every job as failed.

I think a better approach would be to isolate the failed jobs in launch_multi_task and return it as a separate list and only mark those specific ones as failed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could test this by having a test that sends a launch_tasks call with multiple jobs, where only one is invalid and verify that only that is marked as failed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment @phillipleblanc . Let me try and isolate the test assertion to a single job in the unit test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scheduler marks executor dead on a deterministic task launch/decode failure, hanging the job

3 participants