You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
That's working as designed. From the timers documentation:
When delay is larger than 2147483647 or less than 1, the delay will be set to 1.
The WHATWG spec leaves some wiggle room ("This API does not guarantee that timers will run exactly on schedule") so some variation between implementations is to be expected.
Node could be changed to behave more like Chrome but there's a non-zero risk of ecosystem fallout.
Reacted by jakecastelli, James M Snell, Juan José, Darshan Sen, Nikita Skovoroda and Tobias Nießen
I am in favor of changing the behavior for 0 to behave as chrome does.
Besides that, I would actually like to deviate from the spec when it comes to exceeding 2147483647. It is not user friendly at all to just change the timing to a lower number due to the overflow. Instead, we could either accept numbers up until Number.MAX_SAFE_INTEGER and or throw above that limit. It is otherwise pretty much impossible to detect these faulty values.
Reacted by Toni Villena, jakecastelli, Gabriel Machado and Nikita Skovoroda
Changing the timing of this stuff always carries a non-zero risk of breaking apps. While the inconsistency with browsers is unfortunate, I agree that we likely shouldn't change it.
I guess there is no practical use case for the above in any event but just something I found interesting and not really documented somewhere.
Is it possible to discuss the above in tsc agenda meeting as well (despite it is mentioned in the doc - The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.), looks like there is a behaviour change in node v18.x in comparison to previous node versions but it is not being mentioned in the doc history.
There is no behavior change, timers are weird for this and they highly depend on the event loop phases, the startup time of Node.js and the underlining operating system.
Seems like the browsers do improve the situation minimally and as such, we could also do that. It would of course be a breaking change that would have to be communicated.
I won't get to it before the weekend but I plan on opening a PR for the a couple of minor improvements that are all in line with the spec to improve our limits and check CITGM results.
Hi Ruben @BridgeAR 👋 thank you for your thoughts and reply! I followed the link to the spec but didn't find the reference for this one 🤔 would you be able to elaborate:
How to handle zero (the spec only defines to set the value to zero in case the value is below zero)
From what I understand, nodejs will set the negative numbers or 0 or NaN to 1.
We briefly discussed this during the TSC meeting but we did not have a sufficient audience to provide the counter perspective. From my perspective, and I believe it's echoed by @jasnell, we already don't follow the standard today and trying to make this change doesn't meaningfully change that.
In addition, the behaviour of timers is more problematic in a server environment as compared to the browser. Anecdotally I've also seen reliance on this behaviour — as silly as that is — out in the wild and I'm not sure as to the value of a semver major change here.
I would be very clear -1 on this change or other changes to try & align with the spec without some clear evidence that it would be net-positive for the project.
So Chrome “fixed” their lower-end clamping to 1ms? Is that the deal here?
If so Node.js should probably get rid of that too. It was confusing and there are probably more bugs that exist because of that behavior than will exist when removing that behavior.
This issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
Activity
bnoordhuis commentedon Feb 10, 2023
That's working as designed. From the timers documentation:
The WHATWG spec leaves some wiggle room ("This API does not guarantee that timers will run exactly on schedule") so some variation between implementations is to be expected.
Node could be changed to behave more like Chrome but there's a non-zero risk of ecosystem fallout.
jakecastelli commentedon Feb 10, 2023
@bnoordhuis Thanks for clarifying it Ben!
I found even node 14 and node 18 behave a little bit different as well with the following code snippet.
for example:
in node 14 it will be:
however in node 18 it will be
I guess there is no practical use case for the above in any event but just something I found interesting and not really documented somewhere.
BridgeAR commentedon Feb 10, 2023
I am in favor of changing the behavior for 0 to behave as chrome does.
Besides that, I would actually like to deviate from the spec when it comes to exceeding
2147483647. It is not user friendly at all to just change the timing to a lower number due to the overflow. Instead, we could either accept numbers up untilNumber.MAX_SAFE_INTEGERand or throw above that limit. It is otherwise pretty much impossible to detect these faulty values.cjihrig commentedon Feb 11, 2023
I agree completely that the behavior in the spec is not good, but I don't think we should deviate from it.
jasnell commentedon Feb 11, 2023
Changing the timing of this stuff always carries a non-zero risk of breaking apps. While the inconsistency with browsers is unfortunate, I agree that we likely shouldn't change it.
bnoordhuis commentedon Feb 14, 2023
Perhaps someone wants to open a pull request and run it through citgm to get a feel for how bad it impacts the ecosystem?
mcollina commentedon Feb 15, 2023
I don't think we should deviate from the spec. I could be convinced if this would cause no ecosystem breakage.
jakecastelli commentedon Feb 15, 2023
Wanna point out the code blow in chrome browser does not set the delay to 1 which is a little bit surprising.
jakecastelli commentedon Feb 15, 2023
Is it possible to discuss the above in tsc agenda meeting as well (despite it is mentioned in the doc - The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.), looks like there is a behaviour change in node v18.x in comparison to previous node versions but it is not being mentioned in the doc history.

mcollina commentedon Feb 15, 2023
There is no behavior change, timers are weird for this and they highly depend on the event loop phases, the startup time of Node.js and the underlining operating system.
BridgeAR commentedon Feb 15, 2023
The standard itself does actually not provide any restrictions when it comes to zero being handled as one or the maximum value being a 32-bit signed integer. The latter seems to be a historic implementation detail of browsers while not ending in the spec itself.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#run-steps-after-a-timeout
I suggest to split the discussion into three parts:
bnoordhuis commentedon Feb 15, 2023
For the record, node follows what browsers did ca. 2011: nodejs/node-v0.x-archive#593 (comment)
BridgeAR commentedon Feb 15, 2023
The 1 ms minimum has recently been removed from chrome: https://chromestatus.com/feature/4889002157015040
Seems like the browsers do improve the situation minimally and as such, we could also do that. It would of course be a breaking change that would have to be communicated.
I won't get to it before the weekend but I plan on opening a PR for the a couple of minor improvements that are all in line with the spec to improve our limits and check CITGM results.
jakecastelli commentedon Feb 17, 2023
Hi Ruben @BridgeAR 👋 thank you for your thoughts and reply! I followed the link to the spec but didn't find the reference for this one 🤔 would you be able to elaborate:
From what I understand, nodejs will set the negative numbers or 0 or
NaNto 1.apapirovski commentedon Feb 23, 2023
We briefly discussed this during the TSC meeting but we did not have a sufficient audience to provide the counter perspective. From my perspective, and I believe it's echoed by @jasnell, we already don't follow the standard today and trying to make this change doesn't meaningfully change that.
In addition, the behaviour of timers is more problematic in a server environment as compared to the browser. Anecdotally I've also seen reliance on this behaviour — as silly as that is — out in the wild and I'm not sure as to the value of a semver major change here.
I would be very clear -1 on this change or other changes to try & align with the spec without some clear evidence that it would be net-positive for the project.
Fishrock123 commentedon Feb 24, 2023
So Chrome “fixed” their lower-end clamping to 1ms? Is that the deal here?
If so Node.js should probably get rid of that too. It was confusing and there are probably more bugs that exist because of that behavior than will exist when removing that behavior.
github-actions commentedon Jun 21, 2026
This issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
github-actions commentedon Sep 20, 2026
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
timers: allow setTimeout to accept a delay of 0
timers: allow setTimeout to accept a delay of 0