# JSONata interprets message differently from debug node

**URL:** <https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750>\
**Category:** General\
**Tags:** jsonata\
**Created:** [2 March 2025 08:41 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750 "2025-03-02T08:41:47Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [2 March 2025 08:41 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/1 "2025-03-02T08:41:48Z")

</div>

**SYSTEM**  
Raspi 3B+ running recently updated bookworm  
NR 4.0.9  
nodejs 20.18.3

**Problem**  
I have a case where JSONata in a change node is producing (to an element of an object) a different value to that displayed in a debug node, or displayed for the object when written to a Global context data.  
In this case the object is msg.telegram.error and is displayed as a string "AggregateError", but in a JSONata expression which appends msg.telegram.error to a string, it is displayed as an object {"code":"ETIMEDOUT"}. Nothing else shows there is a msg.telegram.error.code in the message, in fact a meessage element can't be a string and a object at the same time.

I did try to copy to msg.telegram.error to msg.errorT in the change node but no difference, unless I ticked DeepCopy, then ErrorT was displayed empty object in debug node.  
I isolated the code into my sandpit and got a copy of msg.telegram by saving it to a globalContext variable telegramTest and saw no change in behaviour.  
global.telegramTest is (as displayed in Context Data sidepane)

```auto
{"isOnline":false,"error":"AggregateError"}

```

and sandpit flow is

```auto
[
    {
        "id": "aa47566793e591e0",
        "type": "ping",
        "z": "db3e3c10fd72ce24",
        "protocol": "Automatic",
        "mode": "triggered",
        "name": "ping Telegram",
        "host": "api.telegram.org",
        "timer": "20",
        "inputs": 1,
        "x": 430,
        "y": 1000,
        "wires": [
            [
                "6a052fd07e1e5a78"
            ]
        ]
    },
    {
        "id": "6a052fd07e1e5a78",
        "type": "switch",
        "z": "db3e3c10fd72ce24",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "false"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 570,
        "y": 1000,
        "wires": [
            [],
            [
                "d7911cc18da7a6a5",
                "75e9c396dc233886",
                "dc4bc07536371b15"
            ]
        ]
    },
    {
        "id": "d7911cc18da7a6a5",
        "type": "change",
        "z": "db3e3c10fd72ce24",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "errorT",
                "pt": "msg",
                "to": "telegram.error",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"Telegram Polling down, Internet and Telegram OK. Error: \" & msg.errorT",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 740,
        "y": 1000,
        "wires": [
            [
                "dc4bc07536371b15"
            ]
        ]
    },
    {
        "id": "dc4bc07536371b15",
        "type": "debug",
        "z": "db3e3c10fd72ce24",
        "name": "debug 17",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 940,
        "y": 1080,
        "wires": []
    },
    {
        "id": "75e9c396dc233886",
        "type": "debug",
        "z": "db3e3c10fd72ce24",
        "name": "debug 18",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "telegram.error",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 940,
        "y": 1120,
        "wires": []
    },
    {
        "id": "81d711184cd97ddc",
        "type": "inject",
        "z": "db3e3c10fd72ce24",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "telegram",
                "v": "telegramTest",
                "vt": "global"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 260,
        "y": 1000,
        "wires": [
            [
                "aa47566793e591e0"
            ]
        ]
    }
]

```

if I change the inject node so msg.telegram is an object (copied from global context data using its copy data button), then the JSONata works as I expected. (new inject node)

```auto
[
    {
        "id": "81d711184cd97ddc",
        "type": "inject",
        "z": "db3e3c10fd72ce24",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "telegram",
                "v": "{\"isOnline\":false,\"error\":\"AggregateError\"}",
                "vt": "json"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 260,
        "y": 1000,
        "wires": [
            [
                "aa47566793e591e0"
            ]
        ]
    }
]

```

So this msg object has hidden data in it, but worse JSONata is using that hidden data whilst displays in the editor like debug node, and Context data display show different. It is like it has a hidden and not hidden value for ".error", one a string the other an object

For information the message comes from the 2nd output of a Telegram Control node from node-red-contrib-telegrambot. I think I know the cause of the error, but I would like it to report the right error in the future? This post is about hidden data, and JSONata behaving differently to NR in general

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [2 March 2025 09:01 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/2 "2025-03-02T09:01:21Z")

</div>

Are you able to post a complete flow that we can test to see the issue?

---

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [3 March 2025 02:52 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/3 "2025-03-03T02:52:00Z")

</div>

OK, took a bit to get it to error. But here is a cut down flow that gets the telegram node to error. In this cast the hidden data is still an object, just an empty object so the final text displays {} in place of the .error string.  
the bot needs a token, so use

```auto
6766654005:AAFDSa7rwFBqZhNTiC4LL3nAWYBC9vNKN7w

```

it is my test bot so I will change the token when your finished.

For telegram Control node to produce an error (and thus the hidden and visible msg.payload.error, the local machine (I use Raspi 3B+) needs to have IPv6 enabled but connected to a network which has no IPv6 connection to internet. Disabling IPv6 on local machine makes the fault in telegram go away. selecting IPv6 or IPv4 in the telegram bot node doesn't help produce the node to error. There appears to be a fault in the nodejs Telegram node that node-red-contrib-Telegrambot uses, this is a separate issue.

The issue is the message 2nd output appears to included hidden data with same "key" as data in the message (msg.payload.error), JSONata uses the hidden data whilst debug nodes and set instruction in change nodes use the visible data (also Debug nodes like Debug 18 do something different).  
Writing the message to Context data appears to write both visible and invisible data but context sidebar only shows the visible data

Flow is

```auto
[
    {
        "id": "81973d9ccf5fcabd",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "aa47566793e591e0",
        "type": "ping",
        "z": "81973d9ccf5fcabd",
        "protocol": "Automatic",
        "mode": "triggered",
        "name": "ping Telegram",
        "host": "api.telegram.org",
        "timer": "20",
        "inputs": 1,
        "x": 470,
        "y": 220,
        "wires": [
            [
                "6a052fd07e1e5a78"
            ]
        ]
    },
    {
        "id": "6a052fd07e1e5a78",
        "type": "switch",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "false"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 610,
        "y": 220,
        "wires": [
            [],
            [
                "d7911cc18da7a6a5",
                "75e9c396dc233886",
                "dc4bc07536371b15"
            ]
        ]
    },
    {
        "id": "d7911cc18da7a6a5",
        "type": "change",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "errorT",
                "pt": "msg",
                "to": "telegram.error",
                "tot": "msg",
                "dc": true
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"Telegram Polling down, Internet and Telegram OK. Error: \" & msg.errorT",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 780,
        "y": 220,
        "wires": [
            [
                "dc4bc07536371b15"
            ]
        ]
    },
    {
        "id": "dc4bc07536371b15",
        "type": "debug",
        "z": "81973d9ccf5fcabd",
        "name": "debug 17",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 980,
        "y": 300,
        "wires": []
    },
    {
        "id": "75e9c396dc233886",
        "type": "debug",
        "z": "81973d9ccf5fcabd",
        "name": "debug 18",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "telegram.error",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 980,
        "y": 340,
        "wires": []
    },
    {
        "id": "81d711184cd97ddc",
        "type": "inject",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "telegram",
                "v": "telegramTest",
                "vt": "global"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 300,
        "y": 220,
        "wires": [
            [
                "aa47566793e591e0"
            ]
        ]
    },
    {
        "id": "ffbd13bc95170a9f",
        "type": "telegram control",
        "z": "81973d9ccf5fcabd",
        "name": "TestBot",
        "bot": "14bfeedab202a370",
        "outputs": 2,
        "checkconnection": true,
        "hostname": "",
        "interval": "10",
        "timeout": "5",
        "x": 100,
        "y": 140,
        "wires": [
            [],
            [
                "c9646e65d4c04159",
                "88214b3be526abaf"
            ]
        ]
    },
    {
        "id": "c9646e65d4c04159",
        "type": "debug",
        "z": "81973d9ccf5fcabd",
        "name": "debug 19",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 280,
        "y": 100,
        "wires": []
    },
    {
        "id": "88214b3be526abaf",
        "type": "change",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "telegram",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 270,
        "y": 160,
        "wires": [
            [
                "aa47566793e591e0"
            ]
        ]
    },
    {
        "id": "14bfeedab202a370",
        "type": "telegram bot",
        "botname": "WombatTest_bot",
        "usernames": "Ian Harrison",
        "chatids": "",
        "baseapiurl": "",
        "testenvironment": false,
        "updatemode": "polling",
        "addressfamily": "6",
        "pollinterval": 300,
        "usesocks": false,
        "sockshost": "",
        "socksprotocol": "socks5",
        "socksport": 6667,
        "socksusername": "anonymous",
        "sockspassword": "",
        "bothost": "",
        "botpath": "",
        "localbothost": "0.0.0.0",
        "localbotport": 8443,
        "publicbotport": 8443,
        "privatekey": "",
        "certificate": "",
        "useselfsignedcertificate": false,
        "sslterminated": false,
        "verboselogging": false
    }
]

```

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [3 March 2025 07:40 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/4 "2025-03-03T07:40:15Z")

</div>

You are in compatibility mode. I suggest using $$.errorT or just errorT

 ![chrome_screenshot_3 Mar 2025 07_38_36 GMT](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/9/79f4975165b46ee2ea20072d2a04d7fd143c1f54.png)

This may have nothing to do with your issue.

As to issue have you tried moving msg.payload rather than setting or try deep copy.

p.s Why are you using JSONata to create the string? The template node is better choice as less resource hungry for this type of thing.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 March 2025 07:57 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/5 "2025-03-03T07:57:15Z")

</div>

Regarding your issue of "hidden properties", the debug output does some curation to format error objects in a particular way. However, after a little investigation, I suspect something is not quite right.

Here is a simple demo I think highlights your issue better (removing all the prerequisites by just generating errors!)

### See how `err` and `error` are "empty" but `errProps` and `errorProps` demonstrate they are clearly NOT empty:

 ![Screenshot 2025-03-03 07.52.52](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/b/eb6be32a400bfb359b6589a564f7a32ba601b27c.png)

```js
try {
    throw new Error('deliberate error')
} catch (error) {
    msg.error = error
    msg.errorProps = {
        message: error.message,
        stack: error.stack,
        cause: error.cause,
    }

    const err = new AggregateError([error],"all errors in here")
    msg.err = err
    msg.errProps = {
        message: err.message,
        stack: err.stack,
        cause: err.cause,
    }

    msg.payload = {
        info: "i am a string prop",
        number: 42,
        error: error,
        err: err,
        fakeError: {
            message: "i am a fake error",
            stack: "blah blah",
            cause: null,
        }
    }

    msg.payload.errorStringifiedParsed = JSON.parse(JSON.stringify(err))
    msg.payload.errorCloned = RED.util.cloneMessage(err);

    node.warn({ _: "the error and some props", err, message: err.message, stack: err.stack, errors: err.errors });
    node.warn({ _: "the error props spread", ...err });
    node.warn({ _: "the error Cloned", errorCloned: msg.payload.errorCloned });
    node.warn({ _: "the error stringified,parsed", errorStringifiedParsed: msg.payload.errorStringifiedParsed });
    node.warn({ _: "the fake error", fakeError: msg.payload.fakeError });

};
return msg;

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 March 2025 08:07 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/6 "2025-03-03T08:07:30Z")

</div>

I suspect this is related to how node-red is packaging data to send to the front end - likely using JSON.stringify somewhere in the chain:

#### `err` is a real error object. its properties have value.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/0/c068548a4dd732aab1d093cd345736c6d8638699.png)

If Node-RED is to handle/show errors better, we will likely need to test the object IS an error.

Unfortunately, [`Error.isError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError#browser_compatibility) is not widely supported yet but there is an official [polyfill](https://github.com/es-shims/Error.isError/blob/main/implementation.js) we could adapt for Node-RED

Issue raised here: [Error objects are not displayed in debug output · Issue #5068 · node-red/node-red · GitHub](https://github.com/node-red/node-red/issues/5068)

---

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [3 March 2025 08:09 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/7 "2025-03-03T08:09:03Z")

</div>

> [@E1cid](#):
>
> st using $$.errorT or just errorT

Thanks for getting back, both of those suggestions made no difference. msg.errorT was introduced by me (originally the JSONata had `..." & msg.telegram.error` but I added the copy to see if it would fix it. I also then added deep copy and it changed (msg.errorT became an empty object).  
In the above Flow, if you change in the change node the set msg.errorT to not be a deep copy (my norm) then the output of the node changes to

```auto
{"payload":"Telegram Polling down, Internet and Telegram OK. Error: {\"code\":\"ETIMEDOUT\"}",
"_msgid":"7a9b925e7f8740d0",
"telegram":{"isOnline":false,"error":"AggregateError"},
"topic":"api.telegram.org",
"errorT":"AggregateError"}

```

The data appended to the string in the JSONata statement changes from empty object to the object with variable with key "code".  
but msg.errorT changes back the string visible in the msg!

JSONata statements

```auto
"Telegram Polling down, Internet and Telegram OK. Error: " & $$.errorT
"Telegram Polling down, Internet and Telegram OK. Error: " & errorT
"Telegram Polling down, Internet and Telegram OK. Error: " & msg.errorT
"Telegram Polling down, Internet and Telegram OK. Error: " & msg.telegram.error

```

all produce the same output (deepcopy off), showing the invisible data in the payload string as above!

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 March 2025 08:26 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/8 "2025-03-03T08:26:03Z")

</div>

As demonstrated above, errors are not correctly displayed but you can simply access the properties e.g...

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/f/afa28962774c5d69f3b21da4d842bd9d1859189e.png)

---

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [3 March 2025 09:30 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/9 "2025-03-03T09:30:05Z")

</div>

Thanks Steve-Mcl, I can work around this easy enough (will replace it all with a template node).

But I am raising this as inconsistent behaviour within node red which I thought is not good and should be fixed.

Just to add, I wrote the message from Telegram Control to a file context data. In the sidebar it shows its value is

```auto
{"isOnline":false,"error":"AggregateError"}

```

If I open the file in .context folder, (using Notepad++) it contains

```auto
{
    "Telegram": {
        "isOnline": false,
        "error": {
            "code": "ETIMEDOUT"
        }
    }
}

```

With this simple Flow

```auto
[
    {
        "id": "81d711184cd97ddc",
        "type": "inject",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "telegram",
                "v": "#:(file)::Telegram",
                "vt": "global"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 260,
        "y": 220,
        "wires": [
            [
                "ae0f1cf2d2d5f631"
            ]
        ]
    },
    {
        "id": "1e533f4854503788",
        "type": "change",
        "z": "81973d9ccf5fcabd",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "message",
                "pt": "msg",
                "to": "telegram.error.message",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "stack",
                "pt": "msg",
                "to": "telegram.error.stack",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 460,
        "y": 300,
        "wires": [
            [
                "4f70a9383e5b8569"
            ]
        ]
    },
    {
        "id": "4f70a9383e5b8569",
        "type": "debug",
        "z": "81973d9ccf5fcabd",
        "name": "debug 2",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 660,
        "y": 300,
        "wires": []
    }
]

```

If I read this Context Data back the debug pane displays it as

```auto
{"_msgid":"8b233012bb14e271",
"payload":1740993795635,
"telegram":{"isOnline":false,"error":"AggregateError"},
"message":"",
"stack":"AggregateError [ETIMEDOUT]: \n at internalConnectMultiple (node:net:1122:18)\n at afterConnectMultiple (node:net:1689:7)"}

```

If this is just read from the Global Context file variable (but which is correct, Context Side Pane or the file it is stored in? So why inconsistent (file contents vse Context side pane)... but where is this other data now from. For info I have disabled the Telegram node for the readback .

I do not think this is good for consistent programing

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 March 2025 09:37 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/10 "2025-03-03T09:37:06Z")

</div>

> [@IanH](#):
>
> I do not think this is good for consistent programing

The issue is a combination of things.

1. Error properties are not enumerable ([ref](https://www.bennadel.com/blog/2874-error-object-properties-are-not-iterable-enumrable-in-node-js.htm))
2. There is a gap between the runtime and your browser meaning data needs to be serialised. Typically this is done with `JSON.stringify` but as demonstrated above, Error objects do not play nice.
3. File based context also means serialisation must be performed
4. How JSONata handles the error object is another matter entirely but i suspect similar issues.

> [@IanH](#):
>
> But I am raising this as inconsistent behaviour within node red which I thought is not good and should be fixed.

I did raise an issue

> [@Steve-Mcl](#):
>
> Issue raised here: [Error objects are not displayed in debug output · Issue #5068 · node-red/node-red · GitHub](https://github.com/node-red/node-red/issues/5068)

Lets see where that leads.

In the mean time, you have a workaround 👍

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [3 March 2025 09:47 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/11 "2025-03-03T09:47:33Z")

</div>

> 1. How JSONata handles the error object is another matter entirely but i suspect similar issues.

Indeed - JSONata is intended to work on JSON compatible types. Error is not a JSON type, so it has to be converted - and only enumerable properties are included. That isn't a behaviour we can change.

---

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [4 March 2025 06:30 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/12 "2025-03-04T06:30:29Z")

</div>

So how do you change a message like this to JSON type, so we can visualise it and thus use the message it with confidence.

That said, the value stored in context memory is JSON when viewed in file

```auto
{
    "Telegram": {
        "isOnline": false,
        "error": {
            "code": "ETIMEDOUT"
        }
    }
}

```

but is shown in the Context Sidebar as

```auto
{"isOnline":false,"error":"AggregateError"}

```

and when you load it (using change node, set) is loaded as (into msg.telegram)

```auto
{"isOnline":false,"error":"AggregateError"}

```

but then a change node, set reference to `msg.telegram.error.stack` yeilds a string

```auto
AggregateError [ETIMEDOUT]: 
    at internalConnectMultiple (node:net:1122:18)
    at afterConnectMultiple (node:net:1689:7)

```

The strings "Aggregate Error" and above string from .stack are nowhere to be seen in the source data loaded from Global Context file (when opened in notepad++)! And I haven't used any JSONata statements.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [4 March 2025 09:49 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/13 "2025-03-04T09:49:28Z")

</div>

> [@IanH](#):
>
> So how do you change a message like this to JSON type, so we can visualise it and thus use the message it with confidence.

since you know and expect the `error` to be in `msg.payload.error` then there are multiple ways. The simplest is to convert it to a new object with regular props.

#### function node

```js
if (typeof msg.payload?.error == 'object') {
  msg.payload.error = {
    name: msg.payload.error.name,
    message: msg.payload.error.message,
    stack: msg.payload.error.stack,
    ...msg.payload.error // get extra enumerable properties that may have been added to the err object
  }
}

```

  

> [@IanH](#):
>
> That said, the value stored in context memory is JSON when viewed in file
> 
> ```auto
> {
> "Telegram": {
> "isOnline": false,
> "error": {
> "code": "ETIMEDOUT"
> }
> }
> }
> 
> ```

`code` is a regular property that `nodejs` adds to the error object (and is therefore enumerable)

> [@IanH](#):
>
> but is shown in the Context Sidebar as
> 
> ```auto
> {"isOnline":false,"error":"AggregateError"}
> 
> ```

That is due to how objects, when implicitly converted to a string (by whatever means) gets its own `toString` method called.

To clarify, an Error object has a `name` property. If the code that generates the error does not set the name, `toString` returns the error type. In this case `AggregateError`

> [@IanH](#):
>
> but is shown in the Context Sidebar as
> 
> ```auto
> {"isOnline":false,"error":"AggregateError"}
> 
> ```
> 
> and when you load it (using change node, set) is loaded as (into msg.telegram)
> 
> ```auto
> {"isOnline":false,"error":"AggregateError"}
> 
> ```

Same as above (name not set, `toString` returns the type name) - its how JS works.

> [@IanH](#):
>
> but then a change node, set reference to `msg.telegram.error.stack` yeilds a string
> 
> ```auto
> AggregateError [ETIMEDOUT]: 
> at internalConnectMultiple (node:net:1122:18)
> at afterConnectMultiple (node:net:1689:7)
> 
> ```

Because you directly called a getter property (in this case the getter named `stack`) so it returned its value.

> [@IanH](#):
>
> The strings "Aggregate Error" and above string from .stack are nowhere to be seen in the source

Because it is NodeJS internal code (compiled)

If you want to dig deeper you would need to interrogate the nested errors inside the `AggregateError`

```auto
if (msg.payload.error?.errors)
  for (e of msg.payload.error.errors) { 
    // check e.stack & e.message props of nested errors here
  }
}

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [4 March 2025 09:56 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/14 "2025-03-04T09:56:13Z")

</div>

Here is a generic routine you can use to convert the error (and any nested errors)

```js
function isError(o) {
  return o instanceof Error || (typeof o === "object" && o !== null && "message" in o && "stack" in o);
}

function toEnumerableErrorObject(o) {
  if (!isError(o)) return o;

  let errorObj = {
    message: o.message,
    stack: o.stack,
    cause: o.cause,
    name: o.name, // Preserve the error name
    ...o, // Include any other enumerable properties
  };

  // Handle AggregateError or similar custom errors with `errors` array
  if (Array.isArray(o.errors)) {
    errorObj.errors = o.errors.map(toEnumerableErrorObject);
  }

  return errorObj;
}

// usage:
if (msg.payload?.error) {
    msg.payload.error = toEnumerableErrorObject(msg.payload.error)
}
return msg

```

---

<div class="post-metadata">

**Author:** ![IanH](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ianh/32/95002_2.png) [@IanH](https://discourse.nodered.org/u/IanH)\
**Post date:** [4 March 2025 11:23 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/15 "2025-03-04T11:23:10Z")

</div>

Thanks Steve for your comprehensive reply. Given in my example, the input is from a context variable file, and only has the text displayed above ("Telegram":.....), then nodered treats a key "error" as a special case and in places like debug node, context side menu and even a set operation in change node, and displays "AggregateError" instead of the error object unless you specify a key from that object (like error.code).  
But cannot see where it has magiced up a value for error.stack when it is not longer in the source (the global context file). Yes it might be their if the input was direct from the Telegram Control node 2nd output, any such data was lost when written to the context variable... except error.code.  
Will have a play with you JS code tomorrow in the sandpit when it get to warm outside for gardening.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [2 June 2025 11:24 UTC](https://discourse.nodered.org/t/jsonata-interprets-message-differently-from-debug-node/95750/16 "2025-06-02T11:24:07Z")

</div>

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