# NR stalls with this specific MQTT input stream

**URL:** <https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709>\
**Category:** General\
**Created:** [3 April 2026 16:03 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709 "2026-04-03T16:03:41Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [3 April 2026 16:03 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/1 "2026-04-03T16:03:41Z")

</div>

This is the first time that NR actually crashes on a specific flow. I guess that will be tricky to debug..

I got a data stream for my BMW car via an external aggregator  
(Project [BMW CarData → MQTT Bridge](https://dj0abr.github.io/bmw-mqtt-bridge/)) . There had been an equivalent NR node but it's no longer functional.

When the car sends the data it will be a stream of about 10-20 MQTT messages, sometimes even double messages with same topics. I am catching these messages with a function node and "distribute" and sort the parameters in different flow variables for further processing:

```flows
[
    {
        "id": "c727cd363836fe5c",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "5b67aa09c7333225",
        "type": "mqtt in",
        "z": "c727cd363836fe5c",
        "name": "BWM CarDataStream",
        "topic": "bmw/WTT5A110607J29109/#",
        "qos": "0",
        "datatype": "json",
        "broker": "43078758.727338",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 280,
        "y": 300,
        "wires": [
            [
                "9a15f9a3fe6a7205"
            ]
        ]
    },
    {
        "id": "9a15f9a3fe6a7205",
        "type": "function",
        "z": "c727cd363836fe5c",
        "name": "set flow variables (single topic)",
        "func": "// proper parameter name now in payload.data\n\nfunction mergeFlatKeysIntoNestedDict(newDict, inputObj, { omitFirst = true, maxDepth = 50 } = {}) {\n for (const fullKey of Object.keys(inputObj)) {\n const parts = fullKey.split(\".\").filter(Boolean);\n let path = omitFirst ? parts.slice(2) : parts;\n\n if (path.length === 0) continue;\n\n // target is a pointer for newDict (avoid shadowing Node-RED's `node`)\n let target = newDict;\n\n for (let i = 0; i < path.length; i++) {\n const seg = path[i];\n const isLeaf = i === path.length - 1;\n\n if (isLeaf) { // final Leaf of the tree, now assign value\n// node.warn(newDict);\n target[seg] = inputObj[fullKey]; // add/overwrite only this leaf\n } else {\n // ensure branch exists; if something non-object is there, replace it\n if (typeof target[seg] !== \"object\" || target[seg] === null || Array.isArray(target[seg])) {\n target[seg] = {};\n }\n // move pointer down to new child\n target = target[seg];\n }\n }\n }\n return newDict;\n}\n\nconst para = msg.payload.data\n\n// get name of flow variable \nif (!para || typeof para !== \"object\") {\n node.warn(\"Expected msg.payload.data to be an object\");\n return { payload: {} };\n}\n\nconst key = Object.keys(para)[0];\nif (!key) {\n node.warn(\"msg.payload.data had no keys\");\n return { payload: {} };\n}\n\nconst nameParts = key.split('.');\nconst name = nameParts[1] ?? nameParts[0];\nnode.warn(`flow variable name: ${name}`)\n\n// read old values if present\nvar para_field = flow.get(name)\nif (para_field == undefined) {\n para_field = {}; //define first\n}\nmergeFlatKeysIntoNestedDict(para_field, para);\nflow.set(name, para_field)\nreturn { \"payload\": para_field }\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 590,
        "y": 300,
        "wires": [
            [
                "c4801b6a0f3040ef",
                "e1d306ae278ad009"
            ]
        ],
        "info": "still not complete\n.env file should better include the option SPLIT_TOPICS=1"
    },
    {
        "id": "c4801b6a0f3040ef",
        "type": "change",
        "z": "c727cd363836fe5c",
        "name": "Flow.drivetrain",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "drivetrain",
                "tot": "flow",
                "dc": true
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 900,
        "y": 300,
        "wires": [
            []
        ]
    },
    {
        "id": "e1d306ae278ad009",
        "type": "change",
        "z": "c727cd363836fe5c",
        "name": "Flow.cabin",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "cabin",
                "tot": "flow",
                "dc": true
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 890,
        "y": 380,
        "wires": [
            []
        ]
    },
    {
        "id": "43078758.727338",
        "type": "mqtt-broker",
        "name": "Smarthome",
        "broker": "192.168.178.40",
        "port": "1883",
        "clientid": "SMARTHOME",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]

```

Every time a data streams arrives NR dashboard gets "offline", and according to the node.warn() messages visible in the log file the function node processes some messages even minutes(!) after receiving.

I observe 2 specific error messages in the log:

```auto
3 Apr 16:33:42 - [info] [mqtt-broker:Smarthome] Disconnected from broker: SMARTHOME@mqtt://192.168.178.40:1883
3 Apr 16:33:42 - [info] [zigbee2mqtt-server:Z2M Broker] MQTT Reconnect
3 Apr 16:36:14 - [info] [zigbee2mqtt-server:Z2M Broker] MQTT Error

```

(Smarthome is my local NR installation) So has my MQTT Broker an "overload" with this particular message stream? Is my ZigBee data stream interfering?

```auto
3 Apr 16:47:44 - [error] [function:set flow variables (single topic)] RangeError: Maximum call stack size exceeded

```

Something is wrong with my javascript function? The message to process looks like:

> {"vin":"XXX6T910607JXXXX","entityId":"58b0daa7-9daa-46f1-859a-55d5169ee206","topic":"XXX6T910607JXXXX","timestamp":"2026-03-15T14:57:33.378Z","data":{"vehicle.cabin.door.status":{"timestamp":"2026-03-15T14:57:29Z","value":"UNLOCKED"}}}

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [3 April 2026 16:15 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/2 "2026-04-03T16:15:26Z")

</div>

> [@haegar33](#):
>
> function node processes some messages even minutes(!) after receiving.

This is usually due to a loop somewhere in your flows. Possibly even in the function code itself.

> [@haegar33](#):
>
> I observe 2 specific error messages in the log:

Probably a timeout due to the issue.

> [@haegar33](#):
>
> So has my MQTT Broker an "overload" with this particular message stream? Is my ZigBee data stream interfering?

Unless you have a heavily overloaded host computer or something is sending 10's of thousands of complex MQTT messages per second, unlikely.

> [@haegar33](#):
>
> `[function:set flow variables (single topic)] RangeError: Maximum call stack size exceeded`

This appears to be the core of the issue. I suspect an error in your function node code. Likely either a loop, a recursive call to a function that is not properly bound.

You should probably share your function code.

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [3 April 2026 16:24 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/3 "2026-04-03T16:24:59Z")

</div>

Sure! The provided flow is probably useless for someone not having the same MQTT input:  
The MQTT message topic like `vehicle.cabin.window.row2.driver.status` is converted in a nested JSON variable but there are no more than 5 levels. Where else could the stack size be exceeded?

```auto
// proper parameter name now in payload.data

function mergeFlatKeysIntoNestedDict(newDict, inputObj, { omitFirst = true, maxDepth = 50 } = {}) {
    for (const fullKey of Object.keys(inputObj)) {
        const parts = fullKey.split(".").filter(Boolean);
        let path = omitFirst ? parts.slice(2) : parts;

        if (path.length === 0) continue;

        // target is a pointer for newDict
        let target = newDict;

        for (let i = 0; i < path.length; i++) {
            const seg = path[i];
            const isLeaf = i === path.length - 1;

            if (isLeaf) { // final Leaf of the tree, now assign value
// node.warn(newDict);
                target[seg] = inputObj[fullKey]; // add/overwrite only this leaf
            } else {
                // ensure branch exists; if something non-object is there, replace it
                if (typeof target[seg] !== "object" || target[seg] === null || Array.isArray(target[seg])) {
                    target[seg] = {};
                }
                // move pointer down to new child
                target = target[seg];
            }
        }
    }
    return newDict;
}

const para = msg.payload.data

// get name of flow variable 
if (!para || typeof para !== "object") {
    node.warn("Expected msg.payload.data to be an object");
    return { payload: {} };
}

const key = Object.keys(para)[0];
if (!key) {
    node.warn("msg.payload.data had no keys");
    return { payload: {} };
}

const nameParts = key.split('.');
const name = nameParts[1] ?? nameParts[0];
node.warn(`flow variable name: ${name}`)

// read old values if present
var para_field = flow.get(name)
if (para_field == undefined) {
    para_field = {}; //define first
}
mergeFlatKeysIntoNestedDict(para_field, para);
flow.set(name, para_field)
return { "payload": para_field }

```

---

<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:** [3 April 2026 16:27 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/4 "2026-04-03T16:27:39Z")

</div>

If you feed in a single message with an inject node what happens?

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [3 April 2026 17:45 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/5 "2026-04-03T17:45:48Z")

</div>

Correct processing, at least for my few constructed simulated input test data. I probably need to simulate the complete burst of messages arriving from the car.. 🫣

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [3 April 2026 21:01 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/6 "2026-04-03T21:01:05Z")

</div>

> [@haegar33](#):
>
> `flow.set(name, para_field)`

How many of these variables are being created and how large are they?

---

<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:** [3 April 2026 21:02 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/7 "2026-04-03T21:02:33Z")

</div>

What rate do they arrive at, or how many are there if they arrive in a burst, and how often are the bursts?

Is there anything else in your flows? Is there something monitoring the context vars you are setting?

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [4 April 2026 07:37 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/8 "2026-04-04T07:37:51Z")

</div>

No idea how/if this could help fix your issue however my OCD has a couple comments on your code:

> [@haegar33](#):
>
> ```auto
> return { "payload": para_field }
> 
> ```

It might well be better to return the initial message from the function:

```auto
msg.payload = para_field
return msg

```

seems to be the convention. In that way you can also add that code to a request-response node as the context is maintained in the msg (i.e. `msg.req` and `msg.res`) object and would be lost if you returned `{ payload: para_field }` from your function.

It might not be relevant today, but tomorrow it will be the next bug to debug.

> [@haegar33](#):
>
> `mergeFlatKeysIntoNestedDict(para_field, para);`

Generally it is good practice to use the return value:

```auto
para_field = mergeFlatKeysIntoNestedDict(para_field, para);

```

this is a general coding convention: don't alter values you pass into a function. Instead use these values in the function and return an alter version of these from function. This avoids unwanted side effects. This is the main difference between "procedures" and "functions" - functions return something and procedures can alter input parameters (i.e. have side effects).

```auto
para_field_one = mergeFlatKeysIntoNestedDict(para_field, para);
para_field_two = mergeFlatKeysIntoNestedDict(para_field, para);

```

generally two calls with the same parameters should return the same values. Because you alter the para\_field redirectly, this isn't the case and can be confusing.

I realise that in this initial version, `mergeFlatKeysIntoNestedDict` is only called once and this isn't an issue but tomorrow will bring more features and changes.

> [@haegar33](#):
>
> ```auto
> var para_field = flow.get(name)
> if (para_field == undefined) {
> para_field = {}; //define first
> }
> 
> ```

This can be shortcutted to `var para_field = flow.get(name) || {}` - `undefined` and `false` will cause the right handside of the `||` (i.e. or operator) to be evaluated.

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [7 April 2026 17:03 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/9 "2026-04-07T17:03:56Z")

</div>

Sorry just back from Eastern break..

> [@Colin](#):
>
> If you feed in a single message with an inject node what happens?

It is processed as expected. It is difficult to simulate the arriving data stream w.r.t timing. Assuming this is a "hiccup" related to this MQTT data.

> [@TotallyInformation](#):
>
> How many of these variables are being created and how large are they?

Its about 6 flow variables sorted by the MQTT topics.

I will follow the hints from @gregorius to polish my javascript function. What I get so far, there is no major flaw in the code itself?

Thanks to all for the support!

---

<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:** [7 April 2026 17:18 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/10 "2026-04-07T17:18:41Z")

</div>

> [@Colin](#):
>
> What rate do they arrive at, or how many are there if they arrive in a burst, and how often are the bursts?
> 
> Is there anything else in your flows? Is there something monitoring the context vars you are setting?

You haven't answered any of those questions, or have I missed a post?

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [7 April 2026 17:30 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/11 "2026-04-07T17:30:05Z")

</div>

You are right, sorry!

Looking at the MQTT timestamps all messages (about 20) arrive in about 4 seconds. Thus the data rate should be not an issue. (MQTT Broker and NR run on a thin server Siemens-Fujitsu 720)

Of course there are other data streams, mostly from my Zigbee network and others. But NR only stalls when this particular car data stream is received.  
As @TotallyInformation already pointed out the "call stack size error" must be further analysed. I will try to debug my function node.

---

<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:** [6 July 2026 17:30 UTC](https://discourse.nodered.org/t/nr-stalls-with-this-specific-mqtt-input-stream/100709/12 "2026-07-06T17:30:51Z")

</div>

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