denoland/deno · error · TypeError
Invalid port (expected number)
Error message
Invalid port (expected number): ${maybePort} What it means
validatePort() accepts only number or numeric-string ports; any other type — undefined/null from clients, booleans, objects, arrays — throws TypeError(`Invalid port (expected number): <value>`). Server-side listen() maps missing null/undefined to port 0 (OS-assigned), so this fires chiefly on connect paths and on structurally wrong values; the printed value usually pinpoints the bad field.
Solutions
- Coerce once at the edge: const port = Number(cfg.port ?? 8080).
- Inspect the value in the error message — '[object Object]' or 'undefined' identifies the mis-wired property; fix the property path.
- Validate with a shared isPort helper before any connect/listen call.
Example fix
// before
Deno.connect({ hostname: "db", port: config.db }); // config.db = { host, port: 5432 }
// after
Deno.connect({ hostname: config.db.host, port: Number(config.db.port) }); Defensive patterns
Strategy: validation
Validate before calling
function toPort(v: unknown, fallback?: number): number {
if (v === null || v === undefined || v === "") {
if (fallback === undefined) throw new TypeError("port missing");
return fallback;
}
const n = Number(v);
if (!Number.isInteger(n) || n < 1 || n > 65535) {
throw new TypeError(`invalid port: ${String(v)}`);
}
return n;
}
Deno.connect({ hostname, port: toPort(cfg.port, 5432) }); Type guard
const isPortLike = (v: unknown): v is number | string => typeof v === "number" || typeof v === "string";
Prevention
- Coerce ports once at the config boundary with Number() and a default
- The error text shows the offending value — '[object Object]' means a wrong property path
- Destructure exactly the numeric field you need instead of passing whole config objects
When it happens
Trigger: `Deno.connect({ port: undefined })`; port: true; port: { port: 8080 } (double-nested config); passing the whole options object where only the port number was expected; an array from splitting a host string.
Common situations: Config typos like options.port.port; env parsing that yields undefined; destructuring the wrong property; defaults applied at the wrong layer so the port slot receives an object or boolean.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/4f473d66e734a8e6.
Report an issue: GitHub.
Appendix: source
Thrown at ext/net/01_net.js:645
}
case "tunnel": {
const { 0: rid, 1: addr } = op_net_listen_tunnel();
return new Listener(rid, addr, "tunnel");
}
default:
throw new TypeError(`Unsupported transport: '${transport}'`);
}
}
function validatePort(maybePort, isServer = false) {
// A missing port means "any available port" (port 0) for servers. Clients
// 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) {View on GitHub (pinned to 9ad36f7a2c)