websockets/ws · critical · TypeError

One and only one of the "port", "server", or "noServer" opti

Error message

One and only one of the "port", "server", or "noServer" options must be specified

What it means

Thrown by the WebSocketServer constructor (lib/websocket-server.js:91-100) when the port/server/noServer options do not satisfy an exactly-one-of constraint. The library needs precisely one of: a port to create+listen its own HTTP server, a pre-existing http.Server passed via server, or noServer mode where you handle the 'upgrade' event yourself. Zero or more-than-one of these is a configuration error and throws TypeError immediately during construction.

Source

Thrown at lib/websocket-server.js:96

      clientTracking: true,
      closeTimeout: CLOSE_TIMEOUT,
      verifyClient: null,
      noServer: false,
      backlog: null, // use default (511 as implemented in net.js)
      server: null,
      host: null,
      path: null,
      port: null,
      WebSocket,
      ...options
    };

    if (
      (options.port == null && !options.server && !options.noServer) ||
      (options.port != null && (options.server || options.noServer)) ||
      (options.server && options.noServer)
    ) {
      throw new TypeError(
        'One and only one of the "port", "server", or "noServer" options ' +
          'must be specified'
      );
    }

    if (options.port != null) {
      this._server = http.createServer((req, res) => {
        const body = http.STATUS_CODES[426];

        res.writeHead(426, {
          'Content-Length': body.length,
          'Content-Type': 'text/plain'
        });
        res.end(body);
      });
      this._server.listen(
        options.port,
        options.host,

View on GitHub (pinned to ae1de54330)

Solutions

  1. Pick exactly one mode: { port } OR { server } OR { noServer: true }.
  2. If embedding in an existing HTTP server, use { server: httpServer } and remove any port option.
  3. If intercepting upgrades manually, use { noServer: true } and call wss.handleUpgrade() from your own 'upgrade' listener.

Example fix

// before
new WebSocketServer({ port: 8080, server: httpServer });

// after
new WebSocketServer({ server: httpServer });
Defensive patterns

Strategy: validation

Validate before calling

function assertServerOptions(opts) {
  const modes = ['port', 'server', 'noServer'].filter((k) => opts[k] != null && opts[k] !== false);
  if (modes.length !== 1) {
    throw new TypeError('Pass exactly one of port, server, or noServer');
  }
}

Type guard

function isValidServerOptions(opts) {
  const has = (k) => opts[k] != null && opts[k] !== false;
  const count = has('port') + has('server') + has('noServer');
  return count === 1;
}

Try / catch

try {
  const wss = new WebSocketServer(opts);
} catch (err) {
  if (/port.*server.*noServer/.test(err.message)) {
    // fix opts to pick exactly one mode, then retry
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling new WebSocketServer({}) (none specified), new WebSocketServer({ port: 8080, server: httpServer }) (port + server), new WebSocketServer({ noServer: true, port: 8080 }) (noServer + port), or new WebSocketServer({ server: httpServer, noServer: true }) (server + noServer). The boolean expression at lines 91-95 explicitly forbids all but the three valid single-option combinations.

Common situations: Migrating from a standalone server to embedding in an existing Express/http server and forgetting to drop the port option; copy-pasting examples that combine noServer with a server; typos like noServer: 'true' (string) being truthy alongside port.

Related errors


AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03). Data as JSON: /data/errors/c344e592076342c2.json. Report an issue: GitHub.