Problem with looping in Execute Workflow node call workflow with IF node

Hello.

I’m trying to do a loop process by passing multiple elements to the Execure Workflow node. I can’t handle it well when the Workflow called by Execure Workflow node can contain IF node. Here is a simple example for illustration.

I call Workflow A on the Execure Workflow node, including the IF node. In Workflow A, multiple “items” created by decomposing the “items” specified by the body parameter of the webhook are passed to Workflow B, and the result for each is obtained.

Workflow B returns “name” for “item” and “OK” if “value” for “item” is 50 or more, otherwise “result” for “NG”.

When multiple elements are passed to the Execution Workflow node, if the IF node results (true, false) are all the same for all the elements, the process can be executed after each element as expected, but even if one different result is present, the process will not be performed normally.

As an example, I share the expected result and the occasional result when passing the following JSON as the body parameter of the webhook call.

{
    "items": [
        {
            "name": "Foo",
            "value": "10"
        },
        {
            "name": "Bar",
            "value": "100"
        },
        {
            "name": "Fizz",
            "value": "10"
        },
        {
            "name": "Buzz",
            "value": "10"
        }
    ]
}

Please share the workflow

Workflow A

{
  "nodes": [
    {
      "parameters": {
        "path": "e77e76b8-c90c-422a-88af-96102eb7e129",
        "responseMode": "lastNode",
        "responseData": "allEntries",
        "options": {}
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        450,
        300
      ],
      "webhookId": "e77e76b8-c90c-422a-88af-96102eb7e129"
    },
    {
      "parameters": {
        "fieldToSplitOut": "items",
        "options": {
          "destinationFieldName": "item"
        }
      },
      "name": "Item Lists",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "items",
              "value": "={{$json[\"body\"][\"items\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "workflowId": "17"
      },
      "name": "Execute Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Item Lists": {
      "main": [
        [
          {
            "node": "Execute Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "Item Lists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Workflow B

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [],
          "number": [
            {
              "value1": "={{$node[\"Start\"].data[\"item\"][\"value\"]}}",
              "operation": "larger",
              "value2": 50
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "result",
              "value": "OK"
            },
            {
              "name": "name",
              "value": "={{$node[\"Start\"].data[\"item\"][\"name\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set1",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        650,
        210
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "result",
              "value": "NG"
            },
            {
              "name": "name",
              "value": "={{$node[\"Start\"].data[\"item\"][\"name\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        650,
        390
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Set1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Share the output returned by the last node

Expected result

[
    {
        "result": "NG",
        "name": "Foo"
    },
    {
        "result": "OK",
        "name": "Bar"
    },
    {
        "result": "NG",
        "name": "Fizz"
    },
{
        "result": "NG",
        "name": "Buzz"
    }
]

Occasional result

[
    {
        "result": "NG",
        "name": "Foo"
    },
    {
        "result": "NG",
        "name": "Bar"
    },
    {
        "result": "NG",
        "name": "Fizz"
    }
]

Information on your n8n setup

  • Running n8n via [Docker, npm, n8n.cloud, desktop app]: Docker

Hi @nrm! What happens here would be the expected behaviour and I hope I can explain why:

When using the Execute Workflow node, it would use the results of the final node in the sub-workflow (your Workflow B). For your workflow B that means either the results from Set 1 or Set 2 are returned, but not both. You could, however, use the Append operation of the Merge node to combine the items from Set1 and Set2 (and then respond with them):

Another problem I spotted in your workflow B was that you use expressions referring to the Start node, e.g. {{$node["Start"].data["item"]["name"]}}. This would be a problem because it means the Set node would look at the item from the Start node with the corresponding index (e.g. Set2 would look for its first item at the first item in the Start node). After the IF node, these are different items though. So instead of $node you can use $json in order to refer to the data the respective Set nodes receive like so: {{$json["item"]["name"]}}.

Once you implement these changes your workflow B would look like so:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [],
          "number": [
            {
              "value1": "={{$json[\"item\"][\"value\"]}}",
              "operation": "larger",
              "value2": 50
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "result",
              "value": "OK"
            },
            {
              "name": "name",
              "value": "={{$json[\"item\"][\"name\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set1",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        680,
        200
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "result",
              "value": "NG"
            },
            {
              "name": "name",
              "value": "={{$json[\"item\"][\"name\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        680,
        380
      ]
    },
    {
      "parameters": {},
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        900,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Set1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set2": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}

The webhook response would then match your expectation (apart from the order, but I reckon that is not an actual problem here):

1 Like

Thank you for the easy-to-understand explanation such as how to return the value of loop processing in n8n and precautions at the time of implementation.

Based on your explanation, I created Workflow C, which is a little more complicated than Workflow A shown above.

In Workflow C, execute the Execute Workflow node that executes Workflow B, and then execute the Switch node that branches at the value of user of Set node. Since Set node is not directly connected to Switch node, it cannot be referenced like $json["user"].

I want to return a JSON that combines the common value of Set node outside the loop process with the result of Workflow B that is different for each item in Workflow C.

If I try to refer to a node that is not directly connected in the loop process like this, the expected process cannot be executed. I would like to know if there is an implementation method that makes this possible.

Workflow C
{
  "nodes": [
    {
      "parameters": {
        "path": "e77e76b8-c90c-422a-88af-96102eb7e129",
        "responseMode": "lastNode",
        "responseData": "allEntries",
        "options": {}
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        450,
        300
      ],
      "webhookId": "e77e76b8-c90c-422a-88af-96102eb7e129"
    },
    {
      "parameters": {
        "fieldToSplitOut": "items",
        "options": {
          "destinationFieldName": "item"
        }
      },
      "name": "Item Lists",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "items",
              "value": "={{$json[\"body\"][\"items\"]}}"
            },
            {
              "name": "user",
              "value": "Tom"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "workflowId": "19"
      },
      "name": "Execute Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ]
    },
    {
      "parameters": {
        "dataType": "string",
        "value1": "={{$node[\"Set\"].json[\"user\"]}}",
        "rules": {
          "rules": [
            {
              "value2": "Tom"
            }
          ]
        },
        "fallbackOutput": 1
      },
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 1,
      "position": [
        1250,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "user",
              "value": "Tom"
            }
          ]
        },
        "options": {}
      },
      "name": "Set1",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        1440,
        210
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "user",
              "value": "No user"
            }
          ]
        },
        "options": {}
      },
      "name": "Set2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        1440,
        360
      ]
    },
    {
      "parameters": {},
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        1660,
        270
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Item Lists": {
      "main": [
        [
          {
            "node": "Execute Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "Item Lists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "Set1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set2": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}

Expected result

[
    {
        "user": "Tom"
    },
    {
        "user": "Tom"
    },
    {
        "user": "Tom"
    },
    {
        "user": "Tom"
    }
]

Occasional result

[
    {
        "user": "Tom"
    },
    {
        "user": "No user"
    },
    {
        "user": "No user"
    },
    {
        "user": "No user"
    }
]

Hi @nrm, in your example you’d be able to reference the first and from the looks of it only item of your Set node with an expression like {{$items("Set")[0].json.user}}. $items() would give you access to all items of a previous node.

To abstract your case a bit and simplify things, have a look at this example:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "user",
              "value": "Tom"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "let results = [];\n\n[ ...Array(10) ].forEach((e, i) => {\n  results.push({\n    json: {\n      value: (Math.random() + 1).toString(36).substring(7)\n    }\n  });\n});\n\nreturn results;"
      },
      "name": "Do Something Else",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "item",
              "value": "={{$json[\"value\"]}}"
            },
            {
              "name": "user",
              "value": "={{$items(\"Set\")[0].json.user}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Reference Original Data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        900,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "Do Something Else",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Do Something Else": {
      "main": [
        [
          {
            "node": "Reference Original Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Here I’m setting a user field at the start (in the “Set” node), then do something completely unrelated to these users that returns 10 random items (in “Do Something Else”). This would be the Item Lists/Execute Workflow part in your workflow C.

In the last node (“Reference Original Data”) I am then reading the user field from the first item of the “Set” node again and add it to every single item (the expression used there would of course work in all other nodes as well):

1 Like

Thank you for answering multiple questions.

In my Workflow C, after making the change how to refer to “user” of “Set” with “Switch” or “Set1” like {{$items("Set")[0].json.user}}, it now returns the expected response. (The data of “Set2” that is not branched by “Switch” was also output, but it has little relation to this question.)

I’ve read the docs, but at that time I didn’t understand the difference between $node and $items. I used $node all the time because I could select it in the Expressions of each node easily and could usually refer to each data with it. I was able to find out that the reference cannot be done well in the processing for multiple data.

1 Like