Error-Circular / Wrong usage of persistent global variables?

First of all a happy new year to all of you!

I'm seeing a lot of error-circular messages and I'm wondering if this is caused by "my way" of handling persistent global variables (I'm storing some historic values, e.g. the highest/lowest temperature seen):

  1. I enabled the Local Filesystem Context Storage

  2. At startup I do the following for every global variable once:
    var globVar = global.get('globVar');
    if(globVar ===undefined)
    {
    globVar = false; // Example for a boolean value
    global.set('globVar ', globVar);
    }

  3. If I want to access the variable I do the following:
    var globVar = global.get('globVar'); //
    ... calculate something here...
    global.set('globVar', globVar);

Could this cause the error-circular warnings? What is the right way of handling global variables (I know, best way is to don't use them at all)?

There's nothing inherently wrong with what you've shared.

Where/when do you see the error? Can you share the actual full output of the error?

What sorts of values are you storing in context? Simple values or more complex objects? If they are objects, how are they generated and do they contain circular references in them?

Hi Nick,

thanks a lot for your help. Unfortunately I'm just beginning with Node Red and I'm struggling to provide the full output of the error - Where can I find this information?

Node-Red-Log just provides the warning itself without any additional information, e.g. "2 Jan 13:28:38 - [warn] error-circular". Same for my debug nodes, e.g. 2.1.2020, 13:57:09 msg : string[14] "error-circular".

So far I struggled to identify the affected node(s), but while writing this message I noticed that I can try to identify the affected nodes by setting one inject to 10s and the rest to 1 hour.

Q: What sorts of values are you storing in context? Simple values or more complex objects?
A: Just simple values like int, float or boolean

Q: If they are objects, how are they generated and do they contain circular references in them?
A: To be honest: I'm not sure, but as I'm just storing simple values I think the answer is "no circular references"

If you name your nodes then it should show the node name in the debug window above the message. It does show an id anyway, but it is easier to track them down if you use names. The Search feature will let you search the flow for a name or an id, or anything else for that matter.

Toss a catch node connected to a debug node (set to display the complete msg object) and see if that helps locate the error,

I dont think naming my nodes will help. Unfortunately the error message doesn't even show the usual node ID (see above). And >95% of my nodes are named anyhow.

I added two nodes (a Catch node connected to a debug node) to see if I get more information. I tried that on every tab but it seems this kind of error is not caught by a catch node. At least I did not get any further information. Just the error message posted above without a node ID.

At this point I would make a backup of your flow and then start tearing it apart till you find the node causing it.

And/or providing your flow so someone else can look at it.

You wrote “local file system” but you don’t defined it in your global.get / global.set calls.
I.e global.set(“globVar”,globVar,”file”)

And to have a safe state it is most of the times a good idea to provide a default (not in point 2 but perhaps point 3)

var globVar=global.get(“globVar”,”file”) || false;

Depending on how context storage has been configured, this may not be needed. If there is only one store, it is the default one used if no store is identified in the api calls.

You are right. I assumed @NrSteffen took the example out of the docs were default is memory.

Another hint could be to take a look on the context tab. There you can inspect the state of global variables and where there stored.

I was typing on my phone having around -5 degrees centigrade... otherwise I wouldn’t pressed send so fast - to get my fingers back into my pocket. Happy New Year!

1 Like

Agree. I will let you guys know if I find something. Thanks for your support.

Ok, I still was not able to find the root cause of my problem, however I found out that it's related to the "Local Filesystem Context Store". I uninstalled NR completely and after a re-installation everything was fine. But once I activated the local file storage the error-circulars started again.

As a workaround I increased the flushInterval to 10 minutes and now the amount of errors has decreased significantly, but they are still there.

settings.js:

contextStorage: {
    default: {
    	module:"localfilesystem",
	config:{flushInterval:600}
    },
},

Doesn't this point towards the way I handle my global variables (see my first question in this thread)? Any ideas?

Thanks!

Btw. tearing my flows apart did not help at all. I increased all inject node periods to >1h and still saw errors. Strange.

The error comes whenever the File Store has to encode your context data to JSON so it can be written to the file. This is why changing the flush interval to 10 minutes will mean you hit the error 10 minutes after updating the context rather than the default 30 seconds.

Yes. Somehow you are putting something into context that includes a circular reference.

Changing the rate of your inject nodes won't change the logic of your flows or the nature of the objects you are trying to store.

So the question again comes back to what sort of data are you trying to store in context.

A good example that came up today was a user trying to store the value returned by setInterval() into context. This value is a complex object with circular references and cannot be converted to JSON.

Thanks, Nick!

I indeed didn't understand that the storing process could just be the symptom, not the issue. So thanks for pointing this out.

Does it make sense to compare the File Store (/home/pi/.node-red/context/global/global.json I guess?) with my context data shown in NR? My understanding is that a missing global in the file would indicate the problem, correct?

Yes, that would be one way to do it - look to see what isn't being persisted as you'd expect.

Everything seems to be ok. Every Global shown in NR is stored in /home/pi/.node-red/context/global/global.json with the value I would expect to see.

Out of 15 Globals 14 are simple types (String, Boolean, Int, Float) and one is automatically generated by a node I installed (https://flows.nodered.org/node/node-red-contrib-homee). The last one is huge, so I'm struggling to compare all values. But as it is stored I guess it should be ok.

Well, to be honest I'm running out of ideas... :smile:

The last node is the reason. Looking at the underlying code of the homee-api library it shows that the object that is populated appears to contain circular references. They're passed by reference, and point to each other. https://github.com/stfnhmplr/homee-api/blob/30362ce63f70a7e87cabe943cad5eeeb0892497e/homee.js this file has that magic.
Those objects are then put in the global context by the node.

1 Like

@afelix,

thanks a lot for your support - that's much more than I have expected. :+1:

Is there a way for me to work around this issue or is this something I have to live with if I keep using both the homee node and Local File Store?

File an issue on the node’s repository, both the node and the underlying library are made by the same person.