Skip to content

http.request can throw immediately but still connect a socket, cause unhandled error #26143

Closed
@zbjornson

Description

@zbjornson
  • Version: v10.15.0, v12.0.0-nightly201902158e68dc53b3
  • Platform: Win10 x64, Linux x64 (4.15.0-1027-gcp Ubuntu 16)
  • Subsystem: http

A call to http.request can throw an error immediately but still connect a socket. When that socket is closed by the other party (e.g. due to timeout), I don't think there's a way to handle the socket hangup error without digging into the http.Agent. Instead, it becomes an unhandled exception.

An edge case, but still seems like a bug. Not sure if there are other ways to cause exceptions besides an invalid timeout type.

const http = require("http");
const {fork} = require("child_process");

if (!process.argv.includes("--server")) {
  const server = fork(__filename, ["--server"]);

  server.on("message", () => { // server is listening
    try {
      http.get({
        port: 3333,
        timeout: null // this causes an error to be thrown immediately
      });
    } catch (ex) {
      // TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number.
      console.log("caught:", ex);

      // There's a socket here, which will timeout and create an uncaught exception
      console.log("after:", http.globalAgent.sockets);
    }
  });

} else {
  const server = http.createServer();
  server.listen(3333, () => {
    process.send("listening");
  });
  server.timeout = 1000;
}
output
caught: TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number. Received type object
    at validateNumber (internal/validators.js:130:11)
    at validateTimerDuration (internal/timers.js:146:3)
    at Socket.setTimeout (net.js:418:11)
    at setRequestSocket (_http_agent.js:361:10)
    at handleSocketCreation_Inner (_http_agent.js:349:7)
    at oncreate (_http_agent.js:224:5)
    at Agent.createSocket (_http_agent.js:229:5)
    at Agent.addRequest (_http_agent.js:185:10)
    at new ClientRequest (_http_client.js:249:16)
    at request (http.js:42:10)
after: { 'localhost:3333:':
   [ Socket {
       connecting: true,
       _hadError: false,
       _handle: [TCP],
       _parent: null,
       _host: 'localhost',
       _readableState: [ReadableState],
       readable: false,
       _events: [Object],
       _eventsCount: 5,
       _maxListeners: undefined,
       _writableState: [WritableState],
       writable: true,
       allowHalfOpen: false,
       _sockname: null,
       _pendingData: null,
       _pendingEncoding: '',
       server: null,
       _server: null,
       timeout: null,
       [Symbol(asyncId)]: 8,
       [Symbol(lastWriteQueueSize)]: 0,
       [Symbol(timeout)]: null,
       [Symbol(kBytesRead)]: 0,
       [Symbol(kBytesWritten)]: 0 } ] }
events.js:167
      throw er; // Unhandled 'error' event
      ^

Error: socket hang up
    at createHangUpError (_http_client.js:323:15)
    at Socket.socketOnEnd (_http_client.js:426:23)
    at Socket.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
    at Socket.socketOnEnd (_http_client.js:426:9)
    at Socket.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions