Why does setTimeout() “break” for large millisecond delay values?

I came across some unexpected behavior when passing a large millisecond value to setTimeout(). For instance,

setTimeout(some_callback, Number.MAX_VALUE);


setTimeout(some_callback, Infinity);

both cause some_callback to be run almost immediately, as if I'd passed 0 instead of a large number as the delay.

Why does this happen?



This is due to setTimeout using a 32 bit int to store the delay so the max value allowed would be


if you try


you get your problem occurring.

I can only presume this is causing some form of internal exception in the JS Engine and causing the function to fire immediately rather than not at all.


Some explanation here: http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html

Timeout values too big to fit into a signed 32-bit integer may cause overflow in FF, Safari, and Chrome, resulting in the timeout being scheduled immediately. It makes more sense simply not to schedule these timeouts, since 24.8 days is beyond a reasonable expectation for the browser to stay open.


Check out the node doc on Timers here: https://nodejs.org/api/timers.html (assuming same across js as well since it's such an ubiquitous term now in event loop based

In short:

When delay is larger than 2147483647 or less than 1, the delay will be set to 1.

and delay is:

The number of milliseconds to wait before calling the callback.

Seems like your timeout value is being defaulted to an unexpected value along these rules, possibly?


Can't comment but to answer all the people. It takes unsigned value ( you can't wait negative milliseconds obviously ) So since max value is "2147483647" when you enter a higher value it start going from 0.

Basically delay = {VALUE} % 2147483647.

So using delay of 2147483648 would make it 1 millisecond, therefore, instant proc.


is actually not an integer. The maximum allowable value for setTimeout is likely 2^31 or 2^32. Try


and you get 1 back instead of 1.7976931348623157e+308.


You can use:

function runAtDate(date, func) {
    var now = (new Date()).getTime();
    var then = date.getTime();
    var diff = Math.max((then - now), 0);
    if (diff > 0x7FFFFFFF) //setTimeout limit is MAX_INT32=(2^31-1)
        setTimeout(function() {runAtDate(date, func);}, 0x7FFFFFFF);
        setTimeout(func, diff);

I stumbled on this when I tried to automatically logout a user with an expired session. My solution was to just reset the timeout after one day, and keep the functionality to use clearTimeout.

Here is a little prototype example:

Timer = function(execTime, callback) {
    if(!(execTime instanceof Date)) {
        execTime = new Date(execTime);

    this.execTime = execTime;
    this.callback = callback;


Timer.prototype = {

    callback: null,
    execTime: null,

    _timeout : null,

     * Initialize and start timer
    init : function() {

     * Get the time of the callback execution should happen
    getExecTime : function() {
        return this.execTime;

     * Checks the current time with the execute time and executes callback accordingly
    checkTimer : function() {

        var now = new Date();
        var ms = this.getExecTime().getTime() - now.getTime();

         * Check if timer has expired
        if(ms <= 0) {

            return false;

         * Check if ms is more than one day, then revered to one day
        var max = (86400 * 1000);
        if(ms > max) {
            ms = max;

         * Otherwise set timeout
        this._timeout = setTimeout(function(self) {
        }, ms, this);

     * Stops the timeout
    stopTimer : function() {


var timer = new Timer('2018-08-17 14:05:00', function() {

And you may clear it with the stopTimer method:



Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.