Read a value from whichever branch ran
A Switch is exclusive — of its arms, exactly one runs. That’s fine while the arms stay separate, but once they reconnect with Merge you often want one downstream step to use whatever that arm produced. Each arm’s step has its own label (storage_read2, storage_read3, …), so a downstream template can’t just say “the file” — it has to say which label, and only one of them actually ran this time.
first_defined() and last_defined() solve this: give them every candidate label, and they return whichever one actually has a value.
The problem
Section titled “The problem”Say a flow reads a file over whichever connected-storage protocol the person picks — FTP, SMB, WebDAV, S3, or SFTP:
Manual → Ask "which protocol?" → Switch on the answer ├─ FTP → Storage list (label: storage_list_ftp) → Storage read (label: storage_read2) ├─ SMB → Storage list (label: storage_list_smb) → Storage read (label: storage_read3) ├─ WebDAV→ Storage list (label: storage_list_webdav)→ Storage read (label: storage_read4) ├─ S3 → Storage list (label: storage_list_s3) → Storage read (label: storage_read5) └─ SFTP → Storage list (label: storage_list_sftp) → Storage read (label: storage_read6) ↓ (all arms reconnect here) Merge ↓ Send pop-up ← wants to show "the file that was read", no matter which arm ranOnly one of storage_read2…storage_read6 exists in the run’s context on any given run — the other four never executed, so they’re simply not there. Without a coalesce helper, the only option is duplicating the pop-up once per branch (five near-identical pop-up steps). first_defined() lets the single pop-up after Merge reference all five candidates at once.
Using it in a templated field
Section titled “Using it in a templated field”Any field that accepts a template — body, a message, a condition — supports first_defined() and last_defined() as regular functions:
{{ first_defined(storage_read2.content, storage_read3.content, storage_read4.content, storage_read5.content, storage_read6.content) }}first_defined(...) walks its arguments left to right and returns the first one that actually has a value — not undefined, not None, not an empty string. last_defined(...) does the same walking right to left. Since only one of the branch labels ever resolves in a given run, either one works; reach for first_defined unless you have a specific reason to prefer the last candidate.
If every candidate is empty (shouldn’t happen if Merge really reconnects all the arms, but templates degrade safely) it renders as an empty string rather than erroring.
Using it on the pop-up’s Attachment field
Section titled “Using it on the pop-up’s Attachment field”Send pop-up’s Attachment field is the exception: it is deliberately not a general template — you type the bare label of the step that fetched the file (e.g. storage_read2), and Routario looks that step’s output up directly. That means the usual {{ label.field }} template syntax doesn’t apply here at all.
For the same switch/case fan-in case, the Attachment field accepts first_defined() / last_defined() too, but written a little differently — over bare labels, not label.content:
{{ first_defined(storage_read2, storage_read3, storage_read4, storage_read5, storage_read6) }}Routario picks the first label in the list whose step actually ran and produced a file, and serves that file inline in the pop-up — exactly as if you’d typed that one label directly.
Worked example
Section titled “Worked example”Continuing the protocol-switch flow above, the pop-up after Merge is configured as:
| Field | Value |
|---|---|
| Title | Fetched file preview |
| Body | {{ first_defined(storage_read2.content, storage_read3.content, storage_read4.content, storage_read5.content, storage_read6.content) }} |
| Attachment | {{ first_defined(storage_read2, storage_read3, storage_read4, storage_read5, storage_read6) }} |
Whichever protocol the person picked, the same single pop-up shows the right preview text and serves the right file — no per-branch duplicates to keep in sync.
Where to go next
Section titled “Where to go next”- Routing a flow — how Switch and Merge fit together.
- Template variables — the full list of filters and helpers available in
{{ }}. - Branch on an AI decision — a worked Switch example on the routing in side.
- Send pop-up — reference — every field on the pop-up step.