mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 08:02:18 +00:00
fix(flows): don't bubble error when continue_on_error is on the last step (#9029)
* fix(flows): don't bubble error when continue_on_error is on the last step When the last step of a flow (or branch/forloop) failed with continue_on_error or skip_failures enabled, should_continue_flow resolved to false (because the flow was at its last step), and the flow was completed with success=false. This made parent flows / subflows treat the run as a failure even though the user explicitly asked to continue past errors. Detect this case and set success=true so the failure is captured in the result but not propagated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: explain why success is overridden post should_continue_flow Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
505f78bd29
commit
192866d519
@@ -1587,6 +1587,16 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
Ok(should_retry)
|
||||
};
|
||||
|
||||
// For a regular module with continue_on_error at the last position, nothing else
|
||||
// overrides `success` — `flow_jobs` is None so the loop/branchall override above
|
||||
// doesn't fire, and `should_continue_flow` resolves to `!is_last_step = false`,
|
||||
// letting the flow complete with success=false and bubble the error up to the
|
||||
// enclosing job/subflow. Detect that case and treat the flow as successful.
|
||||
let recoverable_failure_at_last_step = !success
|
||||
&& is_last_step
|
||||
&& !unrecoverable
|
||||
&& (skip_seq_branch_failure || skip_loop_failures || continue_on_error);
|
||||
|
||||
let should_continue_flow = match success {
|
||||
_ if stop_early => stop_early_err_msg.is_some() && flow_value.failure_module.is_some(), // if stop_early_err_msg some, we want to trigger the error handler before stopping the flow, if any
|
||||
_ if flow_job.is_canceled() => false,
|
||||
@@ -1606,6 +1616,10 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
false => false,
|
||||
};
|
||||
|
||||
if recoverable_failure_at_last_step {
|
||||
success = true;
|
||||
}
|
||||
|
||||
tracing::info!(id = %flow_job.id, root_id = %job_root, success = %success, stop_early = %stop_early, is_last_step = %is_last_step, unrecoverable = %unrecoverable,
|
||||
skip_seq_branch_failure = %skip_seq_branch_failure, skip_loop_failures = %skip_loop_failures,
|
||||
current_module_id = %current_module.map(|x| x.id.clone()).unwrap_or_default(),
|
||||
|
||||
Reference in New Issue
Block a user