Understanding (and fixing ?) warning message

Hello,
In my project, World Meteorological Organization (WMO) Uses Node-RED to Modernize Sharing of Earth-System Data • FlowFuse, I am making extensive use of Redis and therefore of node-red-contrib-redis (node) - Node-RED.
It is an excellent tool to interface with Redis, however, the project is not active any more and the dev is not responding to issues on github.
I have now this message when the flows are restarted:

"Deprecated API warning: Calls to RED.util.evaluateJSONataExpression must include a callback. This will not be optional in Node-RED 4.0. Please identify the node from the following stack and check for an update on npm. If none is available, please notify the node author."

and

Error
    at evaluateJSONataExpression (/usr/src/node-red/node_modules/@node-red/util/lib/util.js:775:18)
    at Object.evaluateNodeProperty (/usr/src/node-red/node_modules/@node-red/util/lib/util.js:673:18)
    at new RedisConfig (/data/node_modules/node-red-contrib-redis/redis.js:15:31)
    at Object.createNode (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/util.js:157:27)
    at Flow.start (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/Flow.js:234:50)
    at async start (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/index.js:398:17)

If I understand correctly the message above, there is (will be) something to be fixed in redis.js.
I suspect the offending code is:

  function RedisConfig(n) {
    RED.nodes.createNode(this, n);
    this.name = n.name;
    this.cluster = n.cluster;
    if (this.optionsType === "") {
      this.options = n.options;
    } else {
      this.options = RED.util.evaluateNodeProperty(
        n.options,
        n.optionsType,
        this
      );
    }
  }

Nevertheless, in the code I don't see any call to RED.util.evaluateJSONataExpression so, I wonder if I am looking at the right place.

So, two questions:

  1. Is this effectively the (future) issue ?
  2. Any suggestion on how to fix it ?

My knowledge of node.js and javascript is close to nil... Any help is welcome !
Thanks.

Hi @greengolfer

In order to fix it.

This

function RedisConfig(n) {
    RED.nodes.createNode(this, n);
    this.name = n.name;
    this.cluster = n.cluster;
    if (this.optionsType === "") {
      this.options = n.options;
    } else {
      this.options = RED.util.evaluateNodeProperty(
        n.options,
        n.optionsType,
        this
      );
    }
  }
  RED.nodes.registerType("redis-config", RedisConfig);

needs to be this

function RedisConfig(n) {
    RED.nodes.createNode(this, n);
    this.name = n.name;
    this.cluster = n.cluster;
    if (this.optionsType === "") {
      this.options = n.options;
    } else {
      RED.util.evaluateNodeProperty(n.options, n.optionsType,this,(err,value) => {
           if(!err) {
            this.options = value
          }
      });
    }
  }
  RED.nodes.registerType("redis-config", RedisConfig);

If this Module is not updated, it will break in Node RED 4.0.0
my suggestion is to attempt a PR on the project, and if still no luck - create a fork of the project, to create a version with the fix - I'm sure many users will appreciate it

1 Like

Thanks for the quick answer.
I have change the function code to what you suggested.
At startup there is not any more the error, but, I have this in the debug window:

3 Dec 12:32:25 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:27 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:29 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:31 - [error] [redis-command:Getall] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:31 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:33 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:35 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:37 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:39 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:41 - [error] [redis-command:Getall] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:41 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:43 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:45 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:47 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:49 - [error] [redis-command:Set] TypeError: Cannot read properties of undefined (reading 'call')
3 Dec 12:32:51 - [error] [redis-command:Getall] TypeError: Cannot read properties of undefined (reading 'call')

So, I suspect the function RedisConfig doesn't quite work as it should.
Maybe (probably), it is my lack of understanding of node.js but in the code you provided I don't quite get how value is initialized...

The last parameter of RED.util.evaluateNodeProperty is a callback with 2 arguments.

  • Error
  • Value

Value is the returned value after RED.util.evaluateNodeProperty is run and evaluated the query

This call is asynchronous meaning code can still be running past the point evaluateNodeProperty is executed, all whilst evaluateNodeProperty is still running.

Its very likely the nodes that are using the RedisConfig are trying to use something from the config before it has finished.

There may be an error provided by the Error parameter.

Try this - and see what is printed in the debug panel

function RedisConfig(n) {
    RED.nodes.createNode(this, n);
    this.name = n.name;
    this.cluster = n.cluster;
    if (this.optionsType === "") {
        this.options = n.options;
    } else {
        RED.util.evaluateNodeProperty(n.options, n.optionsType, this, (err, value) => {
            if (!err) {
                this.options = value
                this.warn(value)

            } else {
                this.error(err)
            }
        });
    }
}
RED.nodes.registerType("redis-config", RedisConfig);

You have to be careful with asynchrony, JSONata is asynchronous, this is why the callback becomes required.
I assume your child node gets redis-config.options before the promise (of options) is resolved

1 Like

Hence :point_up:

If that is true - then I am afraid this will require more work to fix

@knolleary, @Steve-Mcl
It does raise the question of done() being available in the Init of a node?

I cant think of the top of my head if that is available during init of a node?
I certainly don't have use a case for my nodes - but still?

Especially when a config node is using a method requiring a callback during start up?

1 Like

I believe the reason this was not done is that it slows down the pallet loading.

Even if it would become asynchronous, it's also necessary to ensure that the config node is completely initialized before the child node initialization. What about parallel asynchronous functions. A real headache :sweat_smile:

This is the exact point I'm making.
A child node is trying to use the config before its fully inited, because of the introduction of the required asynchronous callbacks.

Having the use of done() will go someway to fixing config nodes needing to use them.

This might require another topic :sweat_smile:

Here is the starting log with the 2nd version:

3 Dec 14:20:37 - [warn] Deprecated API warning: Calls to RED.util.evaluateJSONataExpression must include a callback. This will not be optional in Node-RED 4.0. Please identify the node from the following stack and check for an update on npm. If none is available, please notify the node author.
3 Dec 14:20:37 - [warn] Error
    at evaluateJSONataExpression (/usr/src/node-red/node_modules/@node-red/util/lib/util.js:775:18)
    at Object.evaluateNodeProperty (/usr/src/node-red/node_modules/@node-red/util/lib/util.js:673:18)
    at new RedisConfig (/data/node_modules/node-red-contrib-redis/redis.js:15:18)
    at Object.createNode (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/util.js:157:27)
    at Flow.start (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/Flow.js:234:50)
    at async Object.start [as startFlows] (/usr/src/node-red/node_modules/@node-red/runtime/lib/flows/index.js:398:17)
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?
3 Dec 14:20:37 - [info] Started flows

It looks like the initial issue is still there, plus new problems...

Oh hang on!

try this.

function RedisConfig(n) {
    RED.nodes.createNode(this, n);
    this.name = n.name;
    this.cluster = n.cluster;
    if (this.optionsType === "") {
      this.options = n.options;
    } else {
      RED.util.evaluateNodeProperty(n.options, n.optionsType,this,undefined,(err,value) => {
           if(!err) {
            this.options = value
          }
      });
    }
  }
  RED.nodes.registerType("redis-config", RedisConfig);

it was treating the callback as an msg - and not a callback
This might not stop the child nodes trying to use the Config too early, but that is a different problem if that still continues.

example:

3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?

So you might need to address that also

Remember to restart Node RED

The last code fixed the issue. Thanks !

3 Dec 14:20:37 - [error] [redis-config:Cluster] Missing options in the redis config - Are you upgrading from old version?

Was a consequence of the other problem.

The new code fixed the issue. No more warning about the missing callback and no error like above.

All good. I'll propose a PR to github. Hopefully, it will be approved, otherwise, I'll create a fork.

Thanks again!!

2 Likes

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