Skip to content

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

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)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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