Node red, global variables disappear

I have created several flows in Node red where I have global variables that carries state of a sequence.
I just descovered that the global variable is no more visible in Node red Context Data.
This how it should look like

image
But this morning when I hade a look because my automation didn’t work I descovered that all the global variables where gone.
Have anybody seen that before?
And know what it can depend on?

What do you have in the logs?
How do you run Node-RED?
Did it restart recently?

NodeRed, by default, stores context (node, flow and global) in memory only. What this means is that if the NodeRed process restarts, the context is lost. Most likely, your NR process restarted overnight for some reason (should be noted in your logs).

The way to fix this is setup your context to use the local file system instead of memory only.

https://nodered.org/docs/user-guide/context

I didn’t restart Node-RED, but maybe it restarted it self overnight.

This is how I been using the global variable in a function.
Do I need to declare the variable in a different way?

var var_morning1 = context.global.get("morning1");


if (var_morning1 == "on")
{
    msg.payload = "off";
    global.set("morning1","off");
    return msg;
}

If you are going to use context store.

contextStorage: {
   default: {
       module: "localfilesystem"
   }
}

Where do you put this code?
In a function node?
If so, should I put it in all function nodes?

@code-in-progress have you figured out a way to use multiple contexts? For example, I’d like to use file storage only for a few things and use the memory for most. If I do this:

contextStorage: {
   default: "memoryOnly",
   memoryOnly: { module: 'memory' },
   file: { module: 'localfilesystem' }
}

Any context variable for which I select “file” appears to be inaccessible when trying to access in a home-assistant node:

{{ flow.thing_I_set }}

seems like the HA nodes all use “default” to retrieve context… unless I am missing something.

No. You put it in your settings.js file (in your NodeRed installation folder) and then restart NodeRed.

I’m not sure about how the HA nodes deal with context, but in any function node, you can specify the context storage in any of the get/set methods. I typically use function nodes in front of my HA nodes instead of using the mustache syntax because I’ve seen the same behavior as you.

var a = flow.get("test", memoryOnly);
flow.set("test", "something", file);

https://nodered.org/docs/user-guide/writing-functions#multiple-context-stores

1 Like

Okay, now I have been looking in settings.js file.
Where should I put the code?
Maybe it don’t matter?
It where alot of comment out code in the file.

Yeah. Just find the section that starts with contextStorage: and replace it with what I posted above. Then, restart NodeRed.

There is no section that starts with contextStorage: in my settings.js

There should be a section that looks like this:

// Context Storage
   // The following property can be used to enable context storage. The configuration
   // provided here will enable file-based context that flushes to disk every 30 seconds.
   // Refer to the documentation for further options: https://nodered.org/docs/api/context/
   //
   //contextStorage: {
   //    default: {
   //        module:"localfilesystem"
   //    },
   //},

If you don’t see it, just add what I posted above to the end of the file and try that.

I don’t have that section.
But I have this.

   // Anything in this hash is globally available to all functions.
    // It is accessed as context.global.
    // eg:
    //    functionGlobalContext: { os:require('os') }
    // can be accessed in a function block as:
    //    context.global.os

    functionGlobalContext: {
        // os:require('os'),
        // jfive:require("johnny-five"),
        // j5board:require("johnny-five").Board({repl:false})
    },

Could it have something to do with this?

This is my settings.js file

/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

/**
 * PLEASE NOTE! IMPORTANT! READ!
 *
 * This is a modified version of the settings file. Some parts of the
 * settings are actually controlled by the Hass.io add-on.
 *
 * Parts that are handled by it, are removed from this settings template.
 * The following configuration keys are controlled by the add-on and removed.
 *
 * - uiPort (port setting in the add-on log)
 * - uiHost (no need to manually configure this in the add-on)
 * - debugUseColors (disabled, won't work in the add-on)
 * - flowFile (fixed to flows.json)
 * - credentialSecret (credentials_secret in the add-on configuration)
 * - userDir (is set fixed to `/config/node-red`)
 * - nodesDir (is set fixed to `/config/node-red/nodes`)
 * - adminAuth (known as users in the add-on configuration)
 * - https (ssl settings in the add-on configuration)
 * - logging.console.level (log_level in the add-on configuration)
 * - httpNodeAuth (http_node settings in the add-on configuration)
 * - httpStaticAuth (http_static settings in the add-on configuration)
 * - requireHttps (require_ssl setting in the add-on configuration)
 *
 * If you like to change those settings, some are available via the add-on
 * settings/option in the Hass.io panel in Home Assistant.
 */

module.exports = {

    // Retry time in milliseconds for MQTT connections
    mqttReconnectTime: 15000,

    // Retry time in milliseconds for Serial port connections
    serialReconnectTime: 15000,

    // Retry time in milliseconds for TCP socket connections
    //socketReconnectTime: 10000,

    // Timeout in milliseconds for TCP server socket connections
    //  defaults to no timeout
    //socketTimeout: 120000,

    // Timeout in milliseconds for HTTP request connections
    //  defaults to 120 seconds
    //httpRequestTimeout: 120000,

    // The maximum length, in characters, of any message sent to the debug sidebar tab
    debugMaxLength: 1000,

    // The maximum number of messages nodes will buffer internally as part of their
    // operation. This applies across a range of nodes that operate on message sequences.
    //  defaults to no limit. A value of 0 also means no limit is applied.
    //nodeMaxMessageBufferLength: 0,

    // To disable the option for using local files for storing keys and certificates in the TLS configuration
    //  node, set this to true
    //tlsConfigDisableLocalFiles: true,

    // By default, the Node-RED UI is available at http://localhost:1880/
    // The following property can be used to specify a different root path.
    // If set to false, this is disabled.
    //httpAdminRoot: '/admin',

    // Some nodes, such as HTTP In, can be used to listen for incoming http requests.
    // By default, these are served relative to '/'. The following property
    // can be used to specifiy a different root path. If set to false, this is
    // disabled.
    //httpNodeRoot: '/red-nodes',

    // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot',
    // to apply the same root to both parts.
    //httpRoot: '/red',

    // When httpAdminRoot is used to move the UI to a different root path, the
    // following property can be used to identify a directory of static content
    // that should be served at http://localhost:1880/.
    //httpStatic: '/home/nol/node-red-static/',

    // The maximum size of HTTP request that will be accepted by the runtime api.
    // Default: 5mb
    //apiMaxLength: '5mb',

    // If you installed the optional node-red-dashboard you can set it's path
    // relative to httpRoot
    //ui: { path: "ui" },

    // The following property can be used to disable the editor. The admin API
    // is not affected by this option. To disable both the editor and the admin
    // API, use either the httpRoot or httpAdminRoot properties
    //disableEditor: false,

    // The following property can be used to configure cross-origin resource sharing
    // in the HTTP nodes.
    // See https://github.com/troygoode/node-cors#configuration-options for
    // details on its contents. The following is a basic permissive set of options:
    //httpNodeCors: {
    //    origin: "*",
    //    methods: "GET,PUT,POST,DELETE"
    //},

    // If you need to set an http proxy please set an environment variable
    // called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system.
    // For example - http_proxy=http://myproxy.com:8080
    // (Setting it here will have no effect)
    // You may also specify no_proxy (or NO_PROXY) to supply a comma separated
    // list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk

    // The following property can be used to add a custom middleware function
    // in front of all http in nodes. This allows custom authentication to be
    // applied to all http in nodes, or any other sort of common request processing.
    //httpNodeMiddleware: function(req,res,next) {
    //    // Handle/reject the request, or pass it on to the http in node by calling next();
    //    // Optionally skip our rawBodyParser by setting this to true;
    //    //req.skipRawBodyParser = true;
    //    next();
    //},

    // The following property can be used to verify websocket connection attempts.
    // This allows, for example, the HTTP request headers to be checked to ensure
    // they include valid authentication information.
    //webSocketNodeVerifyClient: function(info) {
    //    // 'info' has three properties:
    //    //   - origin : the value in the Origin header
    //    //   - req : the HTTP request
    //    //   - secure : true if req.connection.authorized or req.connection.encrypted is set
    //    //
    //    // The function should return true if the connection should be accepted, false otherwise.
    //    //
    //    // Alternatively, if this function is defined to accept a second argument, callback,
    //    // it can be used to verify the client asynchronously.
    //    // The callback takes three arguments:
    //    //   - result : boolean, whether to accept the connection or not
    //    //   - code : if result is false, the HTTP error status to return
    //    //   - reason: if result is false, the HTTP reason string to return
    //},

    // Anything in this hash is globally available to all functions.
    // It is accessed as context.global.
    // eg:
    //    functionGlobalContext: { os:require('os') }
    // can be accessed in a function block as:
    //    context.global.os

    functionGlobalContext: {
        // os:require('os'),
        // jfive:require("johnny-five"),
        // j5board:require("johnny-five").Board({repl:false})
    },

    // The following property can be used to order the categories in the editor
    // palette. If a node's category is not in the list, the category will get
    // added to the end of the palette.
    // If not set, the following default order is used:
    paletteCategories: [
        'home_assistant',
        'subflows',
        'input',
        'output',
        'function',
        'social',
        'mobile',
        'storage',
        'analysis',
        'advanced'
    ],

    // Configure the logging output
    logging: {
        // Only console logging is currently supported
        console: {
            // Whether or not to include metric events in the log output
            metrics: false,
            // Whether or not to include audit events in the log output
            audit: false
        }
    },

    // Customising the editor
    editorTheme: {
        projects: {
            // To enable the Projects feature, set this value to true
            enabled: false
        }
    }
}

Just add the contextStorage at the end of your file like this:

editorTheme: {
        projects: {
            // To enable the Projects feature, set this value to true
            enabled: false
        }
    },
    contextStorage: {
        default: "memoryOnly",
        memoryOnly: { module: 'memory' },
        file: { module: 'localfilesystem' }
    }
}

Now, when you set your global variables, specify the context “file” (using global.set()) and your variables should persist over restarts of NR.

1 Like

now I set the global variable like this i a function node

    global.set("morning3","off");

Should it be in another way now?

Yeah, change it to:

global.set("morning3", "off", file);

That will save it to the file context storage instead of memory.

should it be

var a = flow.get("test", memoryOnly);

or

var a = flow.get("test", file);

if I want to write to file?

flow.set("test", "something", file) will write the variable to the file storage. flow.set("test", "something") will write it to the memory storage (as that is set as default).

To get a variable from file storage, you’ll want to use var a = flow.get("test", file). If you don’t specify a storage in the .get method, it’ll grab it from whatever is set as default.

I added followoing code in settings.js file.

contextStorage: {
   default: "memoryOnly",
   memoryOnly: { module: 'memory' },
   file: { module: 'localfilesystem' }
}

Then I have a function node with following code.

var var_morning1 = global.get("morning1", file);

if (var_morning1 == "off")
{
    msg.payload = "on";
    global.set("morning1","on", file);
    return msg;
}

But I get a fault message from the function node.
image

What’s wrong?
Have I added bad code in setttings.js file, should I change it?
Or is it something else?

I just solved it!
The code need to be like this.

var var_morning1 = global.get("morning1", "file");

if (var_morning1 == "off")
{
    msg.payload = "on";
    global.set("morning1","on", "file");
    return msg;
}
1 Like

Hello.
Thansk to all in this topic, it solved my problem 95%
Now the oly thing that is not working is the representation of the global states in file. I only can see the stored in flows.
I checked that the global var stored in files are working, but I can not see them in the lateral bar
image