denoland/deno · error · RangeError
Invalid port (out of range)
Error message
Invalid port (out of range): ${maybePort} What it means
RangeError from validatePort when the port is a valid integer but outside the allowed range. Clients (Deno.connect, Deno.connectTls) must use 1-65535; servers (Deno.listen, Deno.listenTls, listenDatagram) may additionally bind to 0, which asks the OS for an ephemeral port, per the comment 'Servers may bind to port 0 (OS-assigned), clients may not connect to it'. Nothing is dialed or bound when this throws.
Solutions
- Clamp and validate: 1-65535 for connect calls, 0-65535 for listen calls
- Bound any loop that increments a port: stop at 65535
- For an OS-assigned port use Deno.listen({ port: 0 }) and read the real port from listener.addr.port
Example fix
// before
for (let port = 65530; port <= 65540; port++) {
await tryPort(port); // 65536..65540 throw RangeError
}
// after
for (let port = 65530; port <= 65535; port++) {
await tryPort(port);
} Defensive patterns
Strategy: validation
Validate before calling
function assertPortInRange(port: number, isServer: boolean): void {
const min = isServer ? 0 : 1;
if (port < min || port > 65535) {
throw new RangeError(`port ${port} outside ${min}-65535`);
}
} Type guard
function isUsablePort(port: number, isServer: boolean): port is number {
return Number.isInteger(port) && port >= (isServer ? 0 : 1) && port <= 65535;
} Try / catch
try {
await Deno.connect({ hostname, port });
} catch (e) {
if (e instanceof RangeError && e.message.includes('out of range')) {
return null; // skip this candidate port
}
throw e;
} Prevention
- Cap port-increment retry loops at 65535
- Remember port 0 is only meaningful for listeners (OS-assigned); clients must use 1-65535
- Read the assigned ephemeral port from listener.addr.port after listening on 0
When it happens
Trigger: Deno.connect({ port: 0 }) (port 0 is only legal for servers); Deno.listen({ port: 65536 }) (off-by-one at the top of the range); negative ports from arithmetic such as port: -1.
Common situations: Retry or port-scan loops doing port + 1 past 65535; expecting client-side port 0 to mean OS-assigned like it does for listen; config values parsed with a sign or scale error (e.g. 70000).
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/a21db3cebc7de9de.
Report an issue: GitHub.
Appendix: source
Thrown at ext/net/01_net.js:657
// must always specify a port to connect to, so a missing port is left as-is
// and rejected below.
if (isServer && (maybePort === null || maybePort === undefined)) {
maybePort = 0;
}
if (typeof maybePort !== "number" && typeof maybePort !== "string") {
throw new TypeError(`Invalid port (expected number): ${maybePort}`);
}
if (maybePort === "") throw new TypeError("Invalid port: ''");
const port = Number(maybePort);
if (!NumberIsInteger(port)) {
if (NumberIsNaN(port) && !NumberIsNaN(maybePort)) {
throw new TypeError(`Invalid port: '${maybePort}'`);
} else {
throw new TypeError(`Invalid port: ${maybePort}`);
}
} else if (port < (isServer ? 0 : 1) || port > 65535) {
// Servers may bind to port 0 (OS-assigned), clients may not connect to it.
throw new RangeError(`Invalid port (out of range): ${maybePort}`);
}
return port;
}
function createListenDatagram(udpOpFn, unixOpFn) {
return function listenDatagram(args) {
switch (args.transport) {
case "udp": {
const port = validatePort(args.port, true);
const { 0: rid, 1: addr } = udpOpFn(
{
hostname: args.hostname ?? "0.0.0.0",
port,
},
args.reuseAddress ?? false,
args.loopback ?? false,
);
addr.transport = "udp";View on GitHub (pinned to 9ad36f7a2c)