websockets/ws · critical · TypeError
One and only one of the "port", "server", or "noServer"…
Error message
One and only one of the "port", "server", or "noServer" options must be specified
What it means
Thrown by the WebSocketServer constructor at websocket-server.js:91-100. The server needs exactly one way to receive upgrade requests: either it creates its own HTTP server (port), reuses an existing one (server), or defers upgrade handling entirely to the user (noServer). The XOR logic rejects zero options (nothing to listen on) and any combination of two or three (ambiguous ownership of the upgrade event).
Solutions
- Pick exactly one: new WebSocketServer({ port: 8080 }) to create an internal server, new WebSocketServer({ server }) to attach to an existing HTTP server, or new WebSocketServer({ noServer: true }) to handle upgrades manually.
- If migrating modes, delete the now-unused option keys rather than setting them to null/undefined (port == null covers both null and undefined via ==).
- Double-check that no option is accidentally inherited from a spread/merge of another config object.
Example fix
// before
const wss = new WebSocketServer({ port: 8080, server: httpServer });
// after — use ONE mode only
const wss = new WebSocketServer({ server: httpServer }); Defensive patterns
Strategy: validation
Validate before calling
function validateServerOptions(options) {
const modes = ['port', 'server', 'noServer']
.filter(k => options[k] != null && options[k] !== false);
if (modes.length !== 1) {
throw new TypeError(
'Pass exactly one of: { port }, { server }, or { noServer: true }'
);
}
} Type guard
function isSingleServerMode(options) {
const count =
(options.port != null ? 1 : 0) +
(options.server ? 1 : 0) +
(options.noServer ? 1 : 0);
return count === 1;
} Try / catch
try {
wss = new WebSocketServer(config);
} catch (err) {
if (/port.*server.*noServer/.test(err.message)) {
// fix config to use exactly one mode, then retry
config = { noServer: true };
wss = new WebSocketServer(config);
} else throw err;
} Prevention
- Decide your server mode up front and set exactly one of port/server/noServer.
- When migrating modes, delete stale option keys rather than nulling them (port == null matches null and undefined).
- Validate the config object with a single-mode check before constructing.
When it happens
Trigger: Constructing new WebSocketServer({}) with none of the three options; passing both { port: 8080, server: httpServer }; passing { server: httpServer, noServer: true }; passing { port: 8080, noServer: true }; or all three at once. The three-way XOR at lines 92-94 fires for any combination other than exactly one.
Common situations: Forgetting to pass any option (empty constructor); copy-pasting from an example that used `server` while also keeping a `port` from another example; migrating from port mode to noServer mode but forgetting to remove the old option; TypeScript users whose optional fields all evaluate to undefined.
Related errors
- Invalid URL
- server.handleUpgrade() was called more than once with the…
- The server is operating in "noServer" mode
- An invalid or duplicated subprotocol was specified
- Invalid value for parameter
AI-assisted analysis of websockets/ws@c791e707ea (2026-08-06).
Data as JSON: /api/errors/c344e592076342c2.
Report an issue: GitHub.
Appendix: 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 c791e707ea)