Skip to main content

Error nodes

Two nodes for handling errors: Try Catch, a control-flow fork node (architecturally similar to Branch/Switch/Sequence — its own emit() is a defensive stub, and the real compilation happens in the shared exec-chain walker), and Throw, an ordinary exec-passthrough statement node.

Usable both on the main canvas and inside a Function Graph.

Try Catch — error.tryCatch

Runs "Try Body"; if anything in it throws, execution jumps to "Catch Body" instead, with the thrown value available on the "Error" output pin. Optionally, check "Add Finally Statement" to add a third path, "Finally," that always runs after Try Body/Catch Body — whether or not anything actually threw.

Default — no Finally arm

"Add Finally Statement" checked

  • Inputs: in (exec) — "In"
  • Outputs: try (exec) — "Try Body"; catch (exec) — "Catch Body"; finally (exec, only shown when "Add Finally Statement" is checked) — "Finally"; error (value) — "Error"
  • Config fields: "Add Finally Statement" checkbox (off by default) — reveals the "Finally" execution pin
  • Constraints: at least one of Try Body/Catch Body/Finally must have an outgoing wire; the "Error" pin can only be read from inside the Catch Body arm — wiring it into Try Body, Finally, a sibling branch, or anything outside the Catch arm is rejected at validation time.
try {
// ...Try Body arm
} catch (err_abc123) {
console.log(err_abc123); // "Error" reads the caught value
// ...rest of Catch Body arm
} finally {
// ...Finally arm — always runs, whether or not anything threw
}

Unlike Branch's optional else or Switch's optional default, the catch block is always emitted, even if Catch Body is left completely unwired — a JavaScript try statement requires one. The finally block, on the other hand, follows the same "unwired optional arm = no-op" convention as Branch's else: check the box but leave the Finally pin unwired and no finally clause is generated at all. Each arm gets its own scope, exactly like Branch/Switch: a value computed inside Try Body can't be read from Catch Body, Finally, or from outside the node.

Use case: Wrap risky logic — a JSON parse, a lookup that might come back empty, a call to something that can throw — and handle the failure explicitly instead of letting it crash the request. Add a Finally arm when you need guaranteed cleanup — closing a resource, logging that an operation finished — regardless of whether it succeeded or was caught.

Throw — error.throw

Throws whatever is wired (or typed as a literal) into "Value", then — if the throw somehow doesn't propagate further up — continues to "Next".

  • Inputs: in (exec) — "In"; value (value) — "Value"
  • Outputs: out (exec) — "Next"
  • Config fields: none — an unwired "Value" is typed directly on the pin
  • Constraints: "Value" must be either wired or given a literal
throw new Error("something failed");

Wire in a Get Variable bound to an error-typed variable, or a Try Catch's own "Error" output (to re-throw inside a Catch Body), or type a plain string literal directly on the pin.

Use case: Reject a request with a specific error — for example, re-throwing inside a Catch Body after logging it, or throwing a validation failure before any other logic runs.

The "Error" variable type

Variables (see Error in the Variables section) can be declared with data type error, which emits new Error(<message>) — the default value you type becomes the message, JSON.stringify-ed the same way a string variable's default is. Leaving the default empty emits a plain new Error() with no arguments. Works with Get Variable/Set Variable exactly like any other data type.

let myError = new Error("initial error");

Use case: Store a reusable error (with a fixed message) in a variable, then throw it from a Throw node wherever it's needed, instead of typing the same message inline every time.