fix: stop_after_if with empty error_message prevents flow from stopping (#8464)

* fix: stop_after_if with empty error_message no longer prevents flow from stopping

When skip_if_stopped=true and error_message="" were both set, the flow
would continue executing instead of stopping because the empty string
was converted to a default error message, which triggered the error
handler path. Now skip_if_stopped takes precedence and the two options
are treated as mutually exclusive in both backend and frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate system prompts after openflow schema change

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-03-20 20:04:51 +01:00
committed by GitHub
parent 039b79dfe6
commit 1503bf948e
7 changed files with 43 additions and 16 deletions

View File

@@ -286,15 +286,20 @@ struct RecoveryObject {
fn get_stop_after_if_data(stop_after_if: Option<&StopAfterIf>) -> (bool, Option<String>) {
if let Some(stop_after_if) = stop_after_if {
// skip_if_stopped and error_message are mutually exclusive:
// skip_if_stopped=true means clean stop (mark remaining as skipped),
// error_message means stop with error. skip_if_stopped takes precedence.
if stop_after_if.skip_if_stopped {
return (true, None);
}
let err_msg = stop_after_if.error_message.as_ref().and_then(|message| {
let s = if message.is_empty() {
format!("stop after if: {}", stop_after_if.expr)
if message.is_empty() {
Some(format!("stop after if: {}", stop_after_if.expr))
} else {
message.clone()
};
Some(s)
Some(message.clone())
}
});
return (stop_after_if.skip_if_stopped, err_msg);
return (false, err_msg);
}
return (false, None);
}

File diff suppressed because one or more lines are too long

View File

@@ -134,6 +134,12 @@
<Toggle
size="xs"
bind:checked={flowModule.stop_after_if.skip_if_stopped}
on:change={(event) => {
if (flowModule.stop_after_if && event.detail) {
flowModule.stop_after_if.error_message = undefined
raise_error_message_stop_after_if = false
}
}}
options={{
right: 'Label flow as "skipped" if stopped'
}}
@@ -143,13 +149,18 @@
bind:checked={raise_error_message_stop_after_if}
on:change={(event) => {
if (flowModule.stop_after_if) {
flowModule.stop_after_if.error_message = event.detail === false ? undefined : ''
if (event.detail) {
flowModule.stop_after_if.error_message = ''
flowModule.stop_after_if.skip_if_stopped = false
} else {
flowModule.stop_after_if.error_message = undefined
}
}
}}
options={{
right: 'Raise an error message if stopped',
rightTooltip:
'If enabled and the stop condition is met, an error message will be raised. A custom message can be provided; otherwise, a default message will be used.'
'If enabled and the stop condition is met, an error message will be raised. A custom message can be provided; otherwise, a default message will be used. Mutually exclusive with "Label flow as skipped".'
}}
/>
</div>
@@ -269,6 +280,12 @@
<Toggle
size="xs"
bind:checked={flowModule.stop_after_all_iters_if.skip_if_stopped}
on:change={(event) => {
if (flowModule.stop_after_all_iters_if && event.detail) {
flowModule.stop_after_all_iters_if.error_message = undefined
raise_error_message_stop_after_all_if = false
}
}}
options={{
right: 'Label flow as "skipped" if stopped'
}}
@@ -278,14 +295,18 @@
bind:checked={raise_error_message_stop_after_all_if}
on:change={(event) => {
if (flowModule.stop_after_all_iters_if) {
flowModule.stop_after_all_iters_if.error_message =
event.detail === false ? undefined : ''
if (event.detail) {
flowModule.stop_after_all_iters_if.error_message = ''
flowModule.stop_after_all_iters_if.skip_if_stopped = false
} else {
flowModule.stop_after_all_iters_if.error_message = undefined
}
}
}}
options={{
right: 'Raise an error message if stopped',
rightTooltip:
'If enabled and the stop condition is met, an error message will be raised. A custom message can be provided; otherwise, a default message will be used.'
'If enabled and the stop condition is met, an error message will be raised. A custom message can be provided; otherwise, a default message will be used. Mutually exclusive with "Label flow as skipped".'
}}
/>
</div>

View File

@@ -231,7 +231,8 @@ components:
description: JavaScript expression evaluated after the module runs. Can use 'result' (step's result) or 'flow_input'. Return true to stop
error_message:
type: string
description: Custom error message shown when stopping
nullable: true
description: Custom error message when stopping with an error. Mutually exclusive with skip_if_stopped. If set to a non-empty string, the flow stops with this error. If empty string, a default error message is used. If null or omitted, no error is raised.
required:
- expr

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long