Conditions and Errors
Steps run in order, top to bottom. Four tools change that: skip_if leaves
a step out, conditional chooses between two lists of steps, try_catch
runs a fallback when something fails, and on_error decides whether a
failed step stops the run.
Skip a step with skip_if
Section titled “Skip a step with skip_if”Add skip_if to any step. When its condition is true, the step does not
run and the run history shows it as SKIPPED with the condition as the
reason.
{ "name": "send_receipt", "type": "send_email", "skip_if": "{{ is_empty(data.email) }}", "config": { "to": "{{ data.email }}", "subject": "We got your request", "body": "…" } }The condition syntax, and one trap with function calls, are in Variables and expressions.
Branch with conditional
Section titled “Branch with conditional”A conditional step evaluates if and runs the then list when it is
true, the else list when it is false.
{ "name": "route", "type": "conditional", "config": { "if": "{{ data.urgency == 'high' }}", "then": [ { "name": "page_on_call", "type": "send_email", "config": { … } } ], "else": [ { "name": "queue_ticket", "type": "http_post", "config": { … } } ] } }Nested steps are full steps: they can have their own skip_if, on_error
and nested conditionals, and they can read outputs of the steps before them,
including earlier steps in the same list. The conditional step’s output
is branch (then or else) and steps_executed.
Recover with try_catch
Section titled “Recover with try_catch”A try_catch step runs its try list. If a step in it fails, the rest of
the try list is abandoned and the catch list runs instead. With
catch_codes you catch only those error codes;
an empty or missing list catches every error. An error not in the list
passes through and fails the try_catch step itself.
{ "name": "save_copy", "type": "try_catch", "config": { "try": [ { "name": "upload", "type": "drive_upload_file", "config": { … } } ], "catch": [ { "name": "tell_office", "type": "send_email", "config": { … } } ], "catch_codes": [ "external_5xx", "timeout" ] } }The output is branch (try or catch) and error_code. Steps in try
that finished before the failure stay done; nothing is undone.
Choose what a failed step does with on_error
Section titled “Choose what a failed step does with on_error”| Value | What happens |
|---|---|
fail (default) | The run stops and is marked failed, and you are notified. |
continue | The failure is recorded, the step’s output becomes { "failed": true, "error": "<code>" }, and the next step runs. |
retry | On a retryable error, the run is tried again later from this step; see Retries. If the retries run out, it fails like fail. |
Use continue for steps that are nice to have, such as a courtesy email,
and check steps.<name>.failed later if it matters. Use retry on a step
that talks to another service that can be briefly down: http_get,
http_post, http_request, and the Printavo and Drive steps.
When a run fails
Section titled “When a run fails”The run stops at the failing step. Steps before it are not undone: an email already sent stays sent. The failing step shows FAILURE with its error.
Unless the step has on_error: retry and the error can be retried, the
failure is final: the run is marked Failed with the error code and
message, and FlowMint sends a
failure notification.
Fix the cause, then replay the run.
Some errors cannot succeed a second time and are never retried:
external_4xx, auth_failed, validation_failed, config_error,
permission_denied, credential_not_configured, dependency_missing,
file_not_found, file_not_readable, template_not_found,
invalid_input, php_error and workflow_changed. Every other error is
retryable.
Retries
Section titled “Retries”A step with "on_error": "retry" that fails with a retryable error is tried
again automatically: after 1 minute, then 5, then 15, up to
settings.max_retries times (default 3; 0 turns retries off). While it
waits, the run shows Queued with the error and the failed step. If the
last retry fails too, the run is marked Failed and you are notified.
A retry carries on from the step that failed. The steps before it are not
run again — an email already sent is not sent twice — and the values they
produced (steps.*, vars.*) are still there. The failed step itself runs
again, and so does a whole conditional or try_catch that failed
part-way through its own steps.
- Don’t edit a workflow’s steps while a run waits to retry. The retry
then fails with
workflow_changedinstead of carrying on at a step that may have moved; replay it. - A replay is different: it starts again from the first step.
Steps that are safe to run twice
Section titled “Steps that are safe to run twice”A replay runs every step again, so it helps to know which steps repeat harmlessly:
- Safe:
drive_find_or_create_folder,drive_create_folder(returns the existing folder unlessallow_duplicateis on),printavo_find_or_create_customer,fre_delete_entry,fre_delete_entries,pre_upsert_records, and every read-only step. - Repeats its effect:
drive_upload_file,drive_create_text_file,printavo_create_customer,printavo_create_quote,http_postandhttp_request. - Email:
send_emailandsend_email_templateskip a message they already sent in the same run to the same recipient with the same subject within the hour. A replay is a new run, so it sends again.