Reference > Nodes

IF Node

Reference for the n8n IF node -- conditional branching with string, number, boolean, and date comparisons.

ReferenceIntermediate4 min read

The IF node splits a workflow into two branches based on a condition. Items that match the condition flow to the True output; items that do not match flow to the False output. It is the primary tool for conditional logic in n8n.

Output Branches

Branch Description
True Items that satisfy all conditions (AND mode) or at least one condition (OR mode).
False Items that do not satisfy the conditions.

Each branch can connect to different downstream nodes, allowing the workflow to take different actions depending on the data.

Condition Types

Type Available Operators
String equals, not equals, contains, does not contain, starts with, ends with, regex match, is empty, is not empty
Number equals, not equals, greater than, less than, greater than or equal, less than or equal, is empty, is not empty
Boolean is true, is false, is empty, is not empty
Date & Time is after, is before, is empty, is not empty

Multiple Conditions

You can add multiple conditions and combine them with AND or OR logic:

Combine Mode Behavior
AND All conditions must be true for an item to go to the True branch.
OR At least one condition must be true for an item to go to the True branch.

Tip

For complex logic that mixes AND and OR, chain multiple IF nodes in sequence or use the Code node with a custom boolean expression.

Key Parameters

Parameter Description
Conditions One or more conditions to evaluate against each input item.
Combine How multiple conditions are combined: AND or OR.
Value 1 The left side of the comparison. Usually an expression referencing input data (e.g., {{ $json.status }}).
Operation The comparison operator (equals, contains, greater than, etc.).
Value 2 The right side of the comparison. Can be a static value or an expression.

Expression-Based Conditions

For conditions that go beyond the built-in operators, use an expression that returns a boolean:

{{ $json.tags.includes('urgent') && $json.priority > 3 }}

Set the condition type to Boolean and the operator to is true. Put the expression in the Value 1 field.

Note

Expression-based conditions give you the full power of JavaScript inside the IF node without needing a separate Code node.

Common Patterns

Route items by status:

Webhook --> IF (status equals "paid") --> True: Send Invoice / False: Send Reminder

Check a field value and send items down different paths. The True branch handles one case, the False branch handles the other.

Null and empty checks:

HTTP Request --> IF (email is not empty) --> True: Send Email / False: Log Error

Before using a field, verify it exists and is not empty. This prevents downstream nodes from failing on missing data.

Numeric threshold:

Schedule Trigger --> PostgreSQL (count) --> IF (count > 100) --> True: Alert / False: No Action

Compare a numeric value against a threshold to decide whether to trigger an alert.

String pattern matching:

Email Trigger --> IF (subject contains "URGENT") --> True: Slack Alert / False: Normal Processing

Use the contains operator to match partial strings without needing a regex.

Regex matching:

Use the regex match operator for complex pattern matching:

  • Value 1: {{ $json.email }}
  • Operation: regex match
  • Value 2: ^[a-zA-Z0-9._%+-]+@company\.com$

This routes only emails matching the company domain to the True branch.

Tips and Gotchas

Warning: Type mismatches cause unexpected results

If a field contains the string "42" and you compare it as a Number greater than 10, the comparison may fail or behave unexpectedly. Use the Number() function in an expression to cast strings to numbers: {{ Number($json.count) }}.

  • Null vs empty string. The is empty operator catches both null and "". If you need to distinguish between them, use an expression: {{ $json.field === null }}.
  • Case sensitivity. String comparisons are case-sensitive by default. To do a case-insensitive comparison, use an expression with .toLowerCase(): {{ $json.status.toLowerCase() }} equals active.
  • Missing fields. If a referenced field does not exist on an item, the expression returns undefined. The is empty operator treats undefined as empty. Other operators may produce unexpected results. Always check for existence first when the field may not be present.
  • Both branches are optional. You do not need to connect both outputs. If you only care about the True case, leave the False output disconnected and those items will be silently dropped.
  • Multiple IF nodes for multi-way branching. The IF node only supports two branches. For three or more paths, chain IF nodes or use the Switch node instead.

Common Errors

All items go to the False branch even when the condition appears correct. The most common cause is a type mismatch. If the field contains the string "42" and you compare it as a Number greater than 10, the comparison may fail. Cast the value explicitly using {{ Number($json.count) }}. Also check for case sensitivity in string comparisons -- use .toLowerCase() to normalize.

TypeError: Cannot read properties of undefined in the condition expression. The field you are referencing does not exist on the current item. This happens when upstream data is inconsistent or when a previous node returned fewer fields than expected. Add a null check using the is not empty operator first, or use optional chaining in expressions: {{ $json.field?.subfield }}.

Items are not splitting correctly between True and False branches. Verify the Combine mode (AND vs. OR) matches your intent. With AND, all conditions must be true. With OR, any single condition being true sends the item to True. If you have complex mixed logic, consider chaining multiple IF nodes or using a Code node with a custom boolean expression.

See Also

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.