Finally Block — Input & Output
The single guaranteed success port, execution mechanics, and accessible data in the finally scope.
Unconditional Execution Guarantee
The Finally Block's "success" port fires unconditionally at the end of the try/catch lifecycle — after the try scope completes successfully, and after the catch scope completes following an exception. There is no condition, configuration, or runtime state that can prevent it from executing (unless the entire workflow host process crashes).
Output Ports
| Port | Fires When | Notes |
|---|---|---|
| success | Always — after the try scope completes (either successfully or via catch handling). | All workflow variables, exception variables (if error occurred), and execution context are accessible in the finally scope. |
Execution Order Guarantee
The Finally Block fires after all nodes in the catch scope (or all nodes in the try scope on success path) have completed. It is always the last phase of the try/catch/finally trio before execution returns to the main workflow graph.
| Scenario | Execution Order |
|---|---|
| No exception in try scope | Try Block → All try scope nodes → Finally Block → Main workflow continues |
| Exception in try scope | Try Block → Partial try scope (until exception) → Catch Block → All catch scope nodes → Finally Block → Main workflow continues |
Detecting Outcome in Finally Scope
Use an If Condition node as the first node after the Finally Block to branch on whether an exception occurred:
// Condition expression (true = error occurred, false = success)
$mem.__exception_type__ != null
// In a Database Update node (conditional on outcome):
// success path:
{
"status": "completed",
"completed_at": "{{ $now }}",
"error": null
}
// error path:
{
"status": "failed",
"completed_at": "{{ $now }}",
"error": "{{ $mem.__exception_message__ }}"
}
Data Available in Finally Scope
| Data Source | Expression | When Available |
|---|---|---|
| Exception type | $mem.__exception_type__ |
Only when error occurred; null on success path |
| Exception message | $mem.__exception_message__ |
Only when error occurred; null on success path |
| Workflow variables | $var.my_variable |
Always — all variables from try and catch scopes |
| Workflow instance ID | $ctx.workflow_instance_id |
Always |
| Current timestamp | $now |
Always |
The Finally Block produces no output data of its own. Its role is purely structural — it marks the beginning of the unconditional cleanup scope. Any data your cleanup nodes produce (e.g., a log record ID) can be stored in workflow variables for use by subsequent nodes after the trio completes.