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
- Pick exactly one mode: { port } OR { server } OR { noServer: true }.
- If embedding in an existing HTTP server, use { server: httpServer } and remove any port option.
- 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
- Decide your server mode up front: standalone (port), embedded (server), or manual (noServer).
- When migrating modes, delete the now-unused option instead of leaving it set.
- Avoid truthy non-booleans (e.g. noServer: 'true') which still count as set.
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
- The server is operating in "noServer" mode
- server.handleUpgrade() was called more than once with the sa
- The message must not be greater than 123 bytes
- Second argument must be a string or a Uint8Array
- The data size must not be greater than 125 bytes
AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03).
Data as JSON: /data/errors/c344e592076342c2.json.
Report an issue: GitHub.