# Range node out of bounds?

**URL:** https://discourse.nodered.org/t/range-node-out-of-bounds/98865
**Category:** Core Development
**Tags:** range-node
**Created:** [28 August 2025 09:02 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865 "2025-08-28T09:02:03Z")
**Posts on this page:** 17
**Page:** 1

<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: [28 August 2025 09:02 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/1 "2025-08-28T09:02:03Z")

</div>

Hi There,

Just a quick heads up - the range node can be brought to generating values outside of the configured bounds:

```flows
[
    {
        "id": "9b95f8806d032b1a",
        "type": "inject",
        "z": "ae38b2dbd23d1681",
        "g": "b4012d193105c803",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "13.1",
        "payloadType": "num",
        "x": 627,
        "y": 1175,
        "wires": [
            [
                "9867b9610c1786d5"
            ]
        ]
    },
    {
        "id": "9867b9610c1786d5",
        "type": "range",
        "z": "ae38b2dbd23d1681",
        "g": "b4012d193105c803",
        "minin": "0",
        "maxin": "9.5",
        "minout": "0",
        "maxout": "100.5",
        "action": "clamp",
        "round": true,
        "property": "payload",
        "name": "",
        "x": 954,
        "y": 1175,
        "wires": [
            [
                "4fbf1055ffadffe5"
            ]
        ]
    }
]

```

Range node is configured to target range of 0 - 100.5 and the value 13.1 is outside of the incoming range of 0 - 9.5, range node is configured to "limit to the target range".

This example will give a value of 101 because I also set the "round result to the nearest integer".

But the value should really be 100 since that's within the target range.

---

<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: [28 August 2025 09:02 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/2 "2025-08-28T09:02:39Z")

</div>

Best place to report bugs is on github directly

---

<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: [28 August 2025 09:07 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/3 "2025-08-28T09:07:14Z")

</div>

Btw doing the same test but with negative values works, i.e. target range of 0.5 to 100.5 and using a negative values gives 1 not 0, e.g.:

```auto
[{"id":"9d47e88afa90b312","type":"inject","z":"ae38b2dbd23d1681","g":"b4012d193105c803","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-13.1","payloadType":"num","x":784,"y":1231,"wires":[["a9b9805029fecc58"]]},{"id":"a9b9805029fecc58","type":"range","z":"ae38b2dbd23d1681","g":"b4012d193105c803","minin":"0","maxin":"9.5","minout":"0.5","maxout":"100.5","action":"clamp","round":true,"property":"payload","name":"","x":1121,"y":1231,"wires":[["eb733ddd81f3ed5a"]]}]

```

but will give zero if the start value is zero.

---

<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: [28 August 2025 09:36 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/4 "2025-08-28T09:36:21Z")

</div>

> [@knolleary](#):
>
> Best place to report bugs is on github directly

> <https://github.com/node-red/node-red/issues/5255>
>
> \### Current Behavior
> 
> Range node when target ranges are floating points and the …option "round to nearest integer" can return out-of-bounds values.
> 
> \### Expected Behavior
> 
> Remain within the bounds
> 
> \### Steps To Reproduce
> 
> Create a range node with the configuration:
> 
> \- "scale and limit to target range"
> \- input range: 0 - 9.5
> \- target range: 0.5 to 100.5
> \- \[x\] round result to nearest integer
> 
> Payload contains 13.1 (i.e. outside of input range), return value will be 101 -- which is outside of the target range.
> 
> Same thing will happen with negative numbers and using a target range of 0.3 to 100.5 (for example), this will give a value of 0 (second example flow).
> 
> \### Example flow
> 
> \`\`\`
> \[{"id":"e2bce7fd39dbeda5","type":"group","z":"ae38b2dbd23d1681","g":"b4012d193105c803","name":"out of bounds - should be 100","style":{"fill":"#ffbfbf","label":true,"fill-opacity":"0.26"},"nodes":\["9b95f8806d032b1a","9867b9610c1786d5","4fbf1055ffadffe5"\],"x":1134,"y":555.8333536783855,"w":906,"h":82},{"id":"9b95f8806d032b1a","type":"inject","z":"ae38b2dbd23d1681","g":"e2bce7fd39dbeda5","name":"","props":\[{"p":"payload"}\],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"13.1","payloadType":"num","x":1230,"y":596.8333536783855,"wires":\[\["9867b9610c1786d5"\]\]},{"id":"9867b9610c1786d5","type":"range","z":"ae38b2dbd23d1681","g":"e2bce7fd39dbeda5","minin":"0","maxin":"9.5","minout":"0.5","maxout":"100.5","action":"clamp","round":true,"property":"payload","name":"","x":1567,"y":596.8333536783855,"wires":\[\["4fbf1055ffadffe5"\]\]},{"id":"4fbf1055ffadffe5","type":"ut-assert-values","z":"ae38b2dbd23d1681","g":"e2bce7fd39dbeda5","name":"","ignore\_failure\_if\_succeed":false,"rules":\[{"t":"eql","p":"payload","pt":"msg","to":"101","tot":"num"}\],"x":1924,"y":596.8333536783855,"wires":\[\[\]\]},{"id":"7d71420e042e54cd","type":"group","z":"ae38b2dbd23d1681","g":"b4012d193105c803","name":"out of bounds - should be 0","style":{"fill":"#ffbfbf","label":true,"fill-opacity":"0.27"},"nodes":\["fe955924780815a5","7438519f20033109","c88b51800fccb5eb"\],"x":1135,"y":657,"w":906,"h":82},{"id":"fe955924780815a5","type":"range","z":"ae38b2dbd23d1681","g":"7d71420e042e54cd","minin":"0","maxin":"9.5","minout":"0.3","maxout":"100.5","action":"clamp","round":true,"property":"payload","name":"","x":1568,"y":698,"wires":\[\["c88b51800fccb5eb"\]\]},{"id":"7438519f20033109","type":"inject","z":"ae38b2dbd23d1681","g":"7d71420e042e54cd","name":"","props":\[{"p":"payload"}\],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-13.1","payloadType":"num","x":1231,"y":698,"wires":\[\["fe955924780815a5"\]\]},{"id":"c88b51800fccb5eb","type":"ut-assert-values","z":"ae38b2dbd23d1681","g":"7d71420e042e54cd","name":"","ignore\_failure\_if\_succeed":false,"rules":\[{"t":"eql","p":"payload","pt":"msg","to":"0","tot":"num"}\],"x":1925,"y":698,"wires":\[\[\]\]}\]
> \`\`\`
> 
> 
> \### Environment
> 
> \- Node-RED version: 4.0.5
> \- Node.js version:
> \- npm version:
> \- Platform/OS: docker
> \- Browser: firefox

---

<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: [29 August 2025 07:20 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/5 "2025-08-29T07:20:24Z")

</div>

I did some more testing and found another strange configuration: what happens if the from value is less than the to value? I would expect an invalid node error or something. That's not the case and instead I can do something like this:

```flows
[{"id":"1ae5ab0fcaa82ddc","type":"group","z":"ccbf1eb483af3580","name":"limit to target range","style":{"label":true},"nodes":["16f237028e823fb8","6cbcee09b67d8279","bebdc09f44bef0d8","170f49712b8a82f6","a038e05f5cd72970","c16cdfde2b1b9eee","c6cbc0c6a054e9c6","184f031e24c22762","ae4b874bbd4c74d5","e9b4f4a4eac991fb","5b0d291ac537e80e","8581e538618eb3c8"],"x":57,"y":66,"w":697,"h":268},{"id":"16f237028e823fb8","type":"range","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","minin":"100","maxin":"0","minout":"0","maxout":"-100","action":"clamp","round":false,"property":"payload","name":"","x":380,"y":107,"wires":[["bebdc09f44bef0d8"]]},{"id":"6cbcee09b67d8279","type":"inject","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"40","payloadType":"num","x":161,"y":107,"wires":[["16f237028e823fb8"]]},{"id":"bebdc09f44bef0d8","type":"ut-assert-values","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"payload","pt":"msg","to":"-100","tot":"num"}],"x":608,"y":107,"wires":[[]]},{"id":"170f49712b8a82f6","type":"range","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","minin":"100","maxin":"0","minout":"0","maxout":"-100","action":"clamp","round":false,"property":"payload","name":"","x":378,"y":173,"wires":[["c16cdfde2b1b9eee"]]},{"id":"a038e05f5cd72970","type":"inject","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-40","payloadType":"num","x":159,"y":173,"wires":[["170f49712b8a82f6"]]},{"id":"c16cdfde2b1b9eee","type":"ut-assert-values","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"payload","pt":"msg","to":"-100","tot":"num"}],"x":606,"y":173,"wires":[[]]},{"id":"c6cbc0c6a054e9c6","type":"range","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","minin":"100","maxin":"0","minout":"0","maxout":"-100","action":"clamp","round":false,"property":"payload","name":"","x":372,"y":237,"wires":[["ae4b874bbd4c74d5"]]},{"id":"184f031e24c22762","type":"inject","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-20","payloadType":"num","x":153,"y":237,"wires":[["c6cbc0c6a054e9c6"]]},{"id":"ae4b874bbd4c74d5","type":"ut-assert-values","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"payload","pt":"msg","to":"-100","tot":"num"}],"x":600,"y":237,"wires":[[]]},{"id":"e9b4f4a4eac991fb","type":"range","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","minin":"100","maxin":"0","minout":"0","maxout":"-100","action":"clamp","round":false,"property":"payload","name":"","x":374,"y":293,"wires":[["8581e538618eb3c8"]]},{"id":"5b0d291ac537e80e","type":"inject","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":155,"y":293,"wires":[["e9b4f4a4eac991fb"]]},{"id":"8581e538618eb3c8","type":"ut-assert-values","z":"ccbf1eb483af3580","g":"1ae5ab0fcaa82ddc","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"payload","pt":"msg","to":"-100","tot":"num"}],"x":602,"y":293,"wires":[[]]}]

```

The configuration of the range node is this:

 ![Screenshot 2025-08-29 at 09.15.15](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/6/6610dd3c734ea914daf3faed42500d30932b0e11.png)

Regardless of payload (at least those that I tried) the range node always gives me -100 - is that correct? For example, 20 should map to -20. Or 40 to -40. -20 and -40 are correct in being mapped to -100 being outside the input range.

---

<div class="post-metadata">

### Author: ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)
#### Post date: [29 August 2025 07:41 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/6 "2025-08-29T07:41:50Z")

</div>

yes - not quite as I would expect - yet if you specify them the other way round it works ie

from 0 - 100 –\> -100 - 0 IE the inputs are expecting a minimum follow by a maximum to map.

---

<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: [29 August 2025 07:59 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/7 "2025-08-29T07:59:03Z")

</div>

> [@dceejay](#):
>
> them the other way round

Sure but that the configuration I created remains valid - herein lies the issue: I've created a valid configuration that is incorrect in its execution.

In writing my comment, I thought that perhaps having a `from` larger than a `to` is literally ok, i.e., no where in the documentation does it say that one **has** to be less than the other.

I don't know what the intention was when designing the range node, so I can't tell what is correct and what isn't.

EDIT: btw, I did think that the node would do an internally sorting of the values (from & to) to make sure an "invalid" configuration becomes valid but that doesn't seem to be the case.

---

<div class="post-metadata">

### Author: ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)
#### Post date: [29 August 2025 13:20 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/8 "2025-08-29T13:20:54Z")

</div>

Indeed - I don’t disagree - the fact that it works one way round but not the other is not ideal (nor correct). I’m happy to call it a bug and fix it - I can’t believe anyone would rely on the other situation to be the case for correct operation of a flow.

---

<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: [29 August 2025 14:26 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/9 "2025-08-29T14:26:23Z")

</div>

> [@dceejay](#):
>
> I can’t believe anyone would rely on the other situation to be the case for correct operation of a flow.

I doubt that too and spent sometime thinking about what it means to go from 100 to 0 ... in the end it's exactly the same as 0 to 100 if the target range is also reversed.

Btw I had a quick look at the [implementation](https://github.com/node-red/node-red/blob/9ad329e5a184cbd749f4cacf30ae775d1205eba6/packages/node_modules/%40node-red/nodes/core/function/16-range.js) and was surprised about this line:

```auto
n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;

```

Not only does JS support floats as modulo operators but also modulo'ing the divisor with itself 😉 I still don't understand the line - if I add the divisor to the result of doing a modulo, and then do another modulo, don't I just get the original modulo? ... aaaaah ok, you're inverting negative values - now I get it. Thanks for being that rubber duck 😉

---

<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: [29 August 2025 14:31 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/10 "2025-08-29T14:31:36Z")

</div>

> [@dceejay](#):
>
> I’m happy to call it a bug and fix it

I'd go with fixing the validation in the frontend - `from` must be less than `to` and perhaps only integers? Not sure whether that's what is meant by number? I have the feeling that the original implementation assumes integer values?[1] Or is that just my imagination?

[1] = I was thinking that because of the modulo operation but if JS supports float modulo then I guess that is a non-issue.

---

<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: [29 August 2025 14:45 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/11 "2025-08-29T14:45:01Z")

</div>

> [@gregorius](#):
>
> I'd go with fixing the validation in the frontend - `from` must be less than `to` and perhaps only integers

It is perfectly valid to want to scale using float values (think thermocouples that typically output 0.000 ~ 0.041 volts for 0°C ~ 750°C)

---

<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: [29 August 2025 14:50 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/12 "2025-08-29T14:50:40Z")

</div>

> [@Steve-Mcl](#):
>
> float values

Cheers for the clarification.

Then I have to implement a modulo in Erlang that supports floating point values ... damn.

---

<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: [29 August 2025 14:56 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/13 "2025-08-29T14:56:19Z")

</div>

It is entirely reasonable for the node to support mapping from a 0-100 range to a 100-0 range (for example). That would be my expectation. Before changing anything, we need to properly understand the existing behaviour and decide if its sufficiently broken that no one is going to be relying on it if we change things.

---

<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: [29 August 2025 15:15 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/14 "2025-08-29T15:15:37Z")

</div>

> [@knolleary](#):
>
> relying on it if we change things.

I mean you could just as easily codify the existing "broken" behaviour and simply accept it as _the_ behaviour of the range node. Here the broken behaviour I'm referring to is the 100 to 0 and 0 to -100 range (as shown above), not the out-of-bounds behaviour of the original pull request because that is simply wrong - zero and 101 aren't in the bounds of 0.3 - 100.5 (for example).

I'm only asking since I want to create a [unit test](https://github.com/gorenje/erlang-red-flow-testsuite/commit/5c2805957f427ac1e0b81780c7178d14e55e837b#diff-da7d80363e992c174c927bd4003b5b689f5600187dca83ac52d95381b05f83c5) for the range node and have that unit test work with Node-RED and Erlang-Red to have one and the same behaviour on both.

That could also be useful for the Node-RED project since then there is a single gold-standard for the behaviour of the existing nodes and breaking any backward compatibility would immediately error out on a unit test.

---

<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: [29 August 2025 15:23 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/15 "2025-08-29T15:23:04Z")

</div>

Indeed - we do have unit tests for the node already; clearly they don’t cover all combinations as discovered 🙂

---

<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: [29 August 2025 15:48 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/16 "2025-08-29T15:48:16Z")

</div>

> [@knolleary](#):
>
> we do have unit tests

visual - in form of flows? 😉

Just saying that if there was such a repertoire of _visual_ unit tests, then any Node-RED user could create new unit tests to cover areas of usage which is important to them.

Plus such a test suite is great for communicating functionality of nodes ...

---

<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: [28 October 2025 15:49 UTC](https://discourse.nodered.org/t/range-node-out-of-bounds/98865/17 "2025-10-28T15:49:09Z")

</div>

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