denoland/deno · error · TypeError
Invalid port: ''
Error message
Invalid port: ''
What it means
An empty-string port is rejected outright with TypeError("Invalid port: ''"). The dedicated check exists because Number("") === 0, which would otherwise silently bind or connect to port 0 — an OS-assigned or invalid target — instead of surfacing the missing value as an error.
Solutions
- Default falsy to a concrete port: const port = Number(Deno.env.get("PORT") || 3000).
- For URLs, fall back to the scheme default: url.port || (url.protocol === "https:" ? "443" : "80").
- Validate config at startup and fail fast with a clear message before any socket call.
Example fix
// before
const port = Deno.env.get("PORT") ?? ""; // PORT defined but empty
Deno.listen({ port }); // Invalid port: ''
// after
const port = Number(Deno.env.get("PORT") || 3000);
Deno.listen({ port }); Defensive patterns
Strategy: validation
Validate before calling
const envPort = Deno.env.get("PORT");
const port = Number(envPort && envPort.trim() !== "" ? envPort : 3000);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
throw new Error(`invalid PORT configuration: ${JSON.stringify(envPort)}`);
} Type guard
const isNonEmptyPortString = (v: unknown): v is string => typeof v === "string" && v.trim() !== "" && Number.isInteger(Number(v));
Prevention
- Treat empty PORT as unset: `Deno.env.get("PORT") || 3000`
- URL ports are "" when absent — map to the scheme default (443/80) explicitly
- Fail fast on bad port config at startup instead of at first listen/connect
When it happens
Trigger: `port: Deno.env.get("PORT")` when PORT is set but empty; `new URL("https://example.com/").port` which is "" when the URL carries no explicit port; splitting "host:" on ":"; template `${cfg.port}` when cfg.port is an empty string.
Common situations: PORT env var defined-but-empty in .env files or CI variable passthrough; URLs without ports where the scheme default was expected; config merges that leave "" instead of undefined.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/0928a6e5d265919f.
Report an issue: GitHub.
Appendix: source
Thrown at ext/net/01_net.js:647
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) {
switch (args.transport) {
case "udp": {View on GitHub (pinned to 9ad36f7a2c)