9

I am following the course stream-adventure. One of the assignments is to make an http server which converts all the requests to uppercase and return it in the response.

Now I managed to get it working and the assignment passes. However, the console gives me a TimeoutOverflowWarning.

(node:15710) TimeoutOverflowWarning: 4294967296000 does not fit into a 32-bit signed integer.
Timer duration was truncated to 2147483647.
(node:15710) TimeoutOverflowWarning: 4294967296000 does not fit into a 32-bit signed integer.
Timer duration was truncated to 2147483647.

I'm wondering if it's a memory leak or something caused by my code, or if it is something else. Because in the error message 32-bit is mentioned, I wonder if it's related to that I'm using a Macbook Pro from 2016 which runs in 64 bit. (node v10.17.0)

The code:

'use-strict'
const through = require('through2')
const http = require('http')
const port = process.argv[2]

const uppercaser = through(function (buffer, _, next) {
  this.push(buffer.toString().toUpperCase())
  next()
});

const server = http.createServer(function (req, res) {
  if (req.method === 'POST') {
    res.writeHead(200,  { 'Content-Type': 'text/plain' })
    req.pipe(uppercaser).pipe(res)
  } else {
    res.writeHead(404)
    res.end()
  }
});

server.listen(port)

Google searches give various causes of this problem (example 1, example 2) and it seems that most of the solutions are fixed in library used.

Remi
  • 4,663
  • 11
  • 49
  • 84

3 Answers3

7

When I find this type of error is when I use a setInterval function.

This is because the upper limit of the timeout is 2147483647 which is the max limit of 32-bit int.

If you want you can make your own setInterval wrapper

function setDaysTimeout(callback,days) {
    // 86400 seconds in a day
    let msInDay = 86400*1000; 

    let dayCount = 0;
    let timer = setInterval(function() {
        dayCount++;  // a day has passed

        if (dayCount === days) {
           clearInterval(timer);
           callback.apply(this, []);
        }
    }, msInDay);
}

And use it like this:

setDaysTimeout(function() {
     console.log('Four days gone');
}, 4); // fire after 4 days
Basile Lamarque
  • 161
  • 1
  • 7
6

This is the problem related to setTimeout \ setInterval functions. They have a limit of 32-bit as you can see. So that the node is warning you about it:

> setTimeout(console.log, +Infinity)

> (node:19903) TimeoutOverflowWarning: Infinity does not fit into a 32-bit signed integer.
Timeout duration was set to 1.

Since your code does not have any of those, it seems like the problem with some code in library.

I'd recommend to run node with --trace-warnings flag to find the source of warning:

--trace-warnings

Print stack traces for process warnings (including deprecations).

Community
  • 1
  • 1
Eugene Obrezkov
  • 2,910
  • 2
  • 17
  • 34
0

The upper limit of the timeout is 2147483647, which is the max limit of 32-bit int. In order to avoid this you can wait for the max time and then wait for any remaining time.

const timeout = async (callback, time, callbackArguments) => {
  if (!callback || typeof callback !== 'function') throw new Error('Invalid Callback')
  let args = ((callbackArguments && typeof callbackArguments === 'object' && 
    callbackArguments.length > 0) ? callbackArguments : [])
  let max = 2147483647
  if (time > max) {
    let t = Math.floor(time / max)
    let r = time%max
    for (let i = 0; i < t; i++) await (() => new Promise(res => setTimeout(() => res(), max)))();
    if (r) {
        return setTimeout(() => callback(...args), r)
    } else {
        return callback(...args)
    }
  } else {
    return setTimeout(() => callback(...args), time)
  }
}

Use like so

let a = 2
let b = 5
let c = (a, b) => console.log(!a && !b ? 0 : !a && b ? b : a && !b ? a : a + b)
let now = new Date().getTime()
let later = now + 2147483647*5
timeout(c, later-now, [a,b])
Sam Wagner
  • 29
  • 4