Issues using $parent. from a subflow

Hi all,
I am facing issues with using $parent.var from a subflow in order to access the parent flow context. Though my context variable exists, the subflow does not return any value. It does not even return undefined.

the problem is that it works in some cases and does not work on others.

Is there any trace information I can enable or so to find out what actually happens when $parent is being used in a subflow and why it may behave this way when there is definitely a context var?

the only solution guaranteed to work at this stage is if I create the subflow from scratch. If I import a subflow or create a subflow from exisiting nodes , well for that , actually sometimes it works (in very simple flows) and other times it does not ! I could not for certain reproduce it in all situations, therefore my question.

Thanks for help.

Hi @nileio

there is no specific tracing in this area of code.

If you are able to narrow it down at all, or at very least give an example sequence of steps that does reliably reproduce it, that would be very helpful.

hi @knolleary
I originally had a massive flow then I started breaking down into subflows and changed references to use $parent rather than accessing context directly. Everything worked fine on first few tests. I noticed after restart and took me a while to find out that my flow is failing because of the nodes using $parent.
The way i can hardly reproduce is

  1. Have a working flow then create a subflow from the nodes.

  2. some nodes to create a flow context vars (might be inject-change to test but mine is produced by websockets)

  3. test $parent from the subflow using a simple Change-then Debug nodes . It works fine ? then restart nodered, and test again.

I am sorry that I cannot for definite reproduce it but its happening in my environments and I ran out of any possible reason. Almost recreated my whole flow twice !
The thing is if I create a subflow from scratch and copy-past few nodes at a time , then deploy, it seems to work. However, my subflow is large and it is not feasible for me to do that.
The following is an exact replica example of what I have but the difference is in my case the subflow have far many nodes. This one here will just work fine.. but mine will not though they both try access to same context var somecontext

[{"id":"e8c7b15d.e5a8e","type":"subflow","name":"subflow","info":"","category":"","in":[{"x":450,"y":300,"wires":[{"id":"30f1cd29.67ea92"}]}],"out":[{"x":740,"y":300,"wires":[{"id":"30f1cd29.67ea92","port":0}]}],"env":[],"color":"#DEB887"},{"id":"30f1cd29.67ea92","type":"change","z":"e8c7b15d.e5a8e","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$parent.somecontext","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":300,"wires":[[]]},{"id":"5ebfa62a.9466a8","type":"tab","label":"Test parentContext","disabled":false,"info":""},{"id":"de134d62.2a6ab","type":"inject","z":"5ebfa62a.9466a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":515,"y":305,"wires":[["70b61b.1c5fc9e4"]]},{"id":"70b61b.1c5fc9e4","type":"change","z":"5ebfa62a.9466a8","name":"","rules":[{"t":"set","p":"somecontext","pt":"flow","to":"test","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":705,"y":305,"wires":[[]]},{"id":"3456050e.bbd32a","type":"subflow:e8c7b15d.e5a8e","z":"5ebfa62a.9466a8","name":"","env":[],"x":720,"y":370,"wires":[["77bdd3d8.323e5c"]]},{"id":"48785205.3094ec","type":"inject","z":"5ebfa62a.9466a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":570,"y":370,"wires":[["3456050e.bbd32a"]]},{"id":"77bdd3d8.323e5c","type":"debug","z":"5ebfa62a.9466a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":880,"y":370,"wires":[]}]

In order to test this against my problem subflows, I tried with one subflow and removed all connections from the input node of the subflow to the rest of my nodes and just connected the input node with simple Change then Debug as per the example. To my surprise, when I test by using the Inject node on the root flow nothing happens ! I dont even get undefined in the sidebar. It is a bit weird behaviour but this is happening in 4 sub flows that I currently have..

within the subflow:

to retrieve the flow context of the parent, there are multiple ways:

in a function node
flow.get("$parent.somecontext")

the change node, and how you set it up
or with a change node, using the jsonata expression option with:

Make sure to initialize the flow variable upon restart else it will become undefined, you can do this by changing the inject node by enabling the checkbox "Inject once after x seconds, then" or use persistent storage for the variables in settings.

Hi @bakman2

your post appears to be explaining how to use $parent. - does it actually address the issues that @nileio is hitting? Have you spotted something in his example flow that is wrong?

I initially got distracted from the issue indeed, but I think the problem is that the flow variable does not exist when injecting into the subflow. See bottom of my response.

@bakman2 thanks for suggestion. I use $parent.somecontext in the correct way. Both the suggested ways using either Change node and Jsonata in my flow fail the same way. the weird thing is that I dont even get undefined which should be the case when for any reason the value can't be retrieved by the node. what really happens is that I get nothing at all from the output port..
I will upload a video showing the issue with my subflows

I wish it was just that. The variable definitely exists and initialised. I can use it from the root flow with no issue. Note : this issue is little hard to reproduce because it does not happen when you create a subflow from scratch, it happens when you either create a subflow from existing nodes or when you export a flow and import it somewhere else when your subflow has lots of other nodes . as I said in my original post, I am unable to find out what is the exact way to reproduce it, however, it is happening in my environments right now ..

Hi @knolleary and @bakman2 , here is a video demonstrating the problem to the best I could..
notice how the "problem subflow" does not produce any output at all. I took all my other nodes in the problem subflow off-screen to focus on the issue..
let me know your thoughts..

hi @knolleary can you confirm if I need to create an issue on github for this ? I had to re-build all subflows manually one by one to get around it for now so keen to log it for a fix if possible or find out the root cause..

thanks!

update on this issue can be found at https://github.com/node-red/node-red/issues/2513 & https://github.com/drmibell/node-red-contrib-queue-gate/issues/10

I think I can reproduce this issue using just one line of JS code, but I still do not understand the real cause. These are the steps:

  1. Install node-red-contrib-lower. (Almost any other node could be used, but this one is easy.)
  2. Import this flow (based on the one posted by @nileio):
[{"id":"1c9112c4.636bfd","type":"subflow","name":"subflow","info":"","category":"","in":[{"x":220,"y":80,"wires":[{"id":"a73a7eda.92af5"}]}],"out":[{"x":510,"y":80,"wires":[{"id":"a73a7eda.92af5","port":0}]}],"env":[],"color":"#DEB887"},{"id":"a73a7eda.92af5","type":"change","z":"1c9112c4.636bfd","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$parent.somecontext","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":80,"wires":[[]]},{"id":"f35176ad.2aeec","type":"lower-case","z":"1c9112c4.636bfd","name":"","x":380,"y":140,"wires":[[]]},{"id":"b105ba0c.0e5f","type":"inject","z":"275b6d65.ead67a","name":"inject #1","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":80,"wires":[["75695b82.5772ac"]]},{"id":"75695b82.5772ac","type":"change","z":"275b6d65.ead67a","name":"","rules":[{"t":"set","p":"somecontext","pt":"flow","to":"test","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":80,"wires":[[]]},{"id":"50266c7d.cfbd84","type":"subflow:1c9112c4.636bfd","z":"275b6d65.ead67a","name":"","env":[],"x":385,"y":145,"wires":[["6a4563f.1df9e9c"]]},{"id":"17bdb382.6c814c","type":"inject","z":"275b6d65.ead67a","name":"inject #2","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":235,"y":145,"wires":[["50266c7d.cfbd84"]]},{"id":"6a4563f.1df9e9c","type":"debug","z":"275b6d65.ead67a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":545,"y":145,"wires":[]}]
  1. At this point, triggering inject #2 should give undefined as the debug output. If you trigger inject #1, followed by inject #2, the debug output should be "test" and continue that way for future triggers of inject #2. (All this is to be expected.)
  2. Edit lowercase.js (generally found in ~/.node-red/node_modules/node-red-contrib-lower/lower/) by adding one line (the 5th):
module.exports = function(RED) {
    function LowerCaseNode(config) {
        RED.nodes.createNode(this,config);
        var node = this;
        var context = node.context();
        this.on('input', function(msg) {
            msg.payload = msg.payload.toLowerCase();
            node.send(msg);
        });
    }
    RED.nodes.registerType("lower-case",LowerCaseNode);
}
  1. Repeat step 3. There should be no change.
  2. Stop and restart NR.
  3. Triggering inject #2 now produces no output from the subflow.

Once you have reached step 6, the only way I have found to restore normal behavior is to edit the subflow template to remove the lower-case node AND restart NR.

I suspect that an instance of a node inside a subflow does not really have its own node context, at least not in the usual way, but I've reached the limit of my understanding/guesswork.

1 Like

Thanks @drmibell

I updated the issue this morning.

The issue is all of the nodes you've identified access their context in their constructor function. They are absolutely allowed to do that, but it exposes a problem with the way subflow instance context is created - it gets done after the nodes are created. But as the nodes have already accessed their context by that time, it breaks the link between the node context and its parent.

I've got a fix working, but it needs lots of testing as it has changed some of the core logic around context handling.

1 Like

Thanks, Nick. So my guess was "close but no cigar."

Should I put notes in the documentation of my nodes to warn against using them in subflows until the fix is available?

Just for the record, I believe this has been fixed in NR version 1.0.5 :slightly_smiling_face:

2 Likes

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.