core.if

IF (core.if)

Route each item down one of two branches — true (top output) or false (bottom output) — based on conditions evaluated per item. Items are never dropped: everything lands on exactly one branch, in input order, with binary attachments intact.

Parameters

ParameterTypeDefaultDescription
conditionslist of conditions[]Each condition is data_type + left + operator + right. left/right accept {{ }} expressions, evaluated per item.
combineand | orandand: every condition must hold. or: any one is enough.

Operators by data type

Data typeOperators
stringequals, not equals, contains, does not contain, starts with, ends with, matches regex, is empty, is not empty
numberequals, not equals, greater/less than, greater/less or equal, is empty, is not empty
booleanis true, is false, equals, not equals

"Is empty / is not empty / is true / is false" take no right-hand value.

Behavior

conditions  $json.n >= 10   (number)
input       {"n": 5}  {"n": 20}  {"n": 10}
true   →    {"n": 20}  {"n": 10}
false  →    {"n": 5}

Tolerant comparison, never a crash. A condition that can't be evaluated — comparing text with greater than, an invalid regex, a boolean check on "maybe" — makes that condition false (with a logged warning) and the item routes to the false branch. A routing node never fails the run over the shape of its data.

Numbers compare numerically under the ordered operators: "10" > "9" is true even when both sides arrive as strings. Boundaries behave as labeled — >= 10 matches 10, > 10 doesn't.

Boolean coercion understands common tokens: true/1/yes/y/on are true, false/0/no/n/off and the empty string are false. None is false.

Regex matches anywhere in the value (search, not full-match) — anchor with ^ and $ when you mean the whole string.

Empty branches skip downstream. If nothing lands on a branch, the nodes wired to it don't run at all (they're skipped, not run with zero items) — and a merge below still fires on its live inputs.

Quirks & tips

  • The string type does not coerce numbers. With data_type: string, the number 10 does not equal the string "10". Comparing numbers? Pick the number data type — its equality coerces both sides.
  • A missing reference stops the node. The never-crash rule covers comparing values; {{ $json.nope }} on an item without nope is an expression error that fails the run. Test optional fields with is empty on a field that exists, or guard upstream.
  • 0 is not "empty". Empty means null, "", [], or {} — the number zero passes is not empty.
  • No conditions at all: with and every item routes true (vacuous truth); with or every item routes false. Add a condition before trusting the output.
  • contains on a list checks membership ("prod" in tags); on a string it checks substring (the right side is stringified).
  • starts with / ends with stringify both sides — 2024 starts with "20".

Related

  • Filter — same condition system, but keeps/drops on a single output instead of routing to two.
  • Switch — route across up to 8 named outputs, first match wins.
  • Set — reshape items before or after routing.