denoland/deno · error · TypeError
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
Error message
The "options.port" property must be one of type number or string
What it means
In net.connect()'s connect path, once options.port is defined it must be a number or a string (numeric string); validatePort and the port |= 0 truncation follow. Any other type throws ERR_INVALID_ARG_TYPE — notably null (typeof null === 'object'), plain objects, booleans, and BigInts.
Source
Thrown at ext/node/polyfills/net.ts:1069
function _lookupAndConnect(self: Socket, options: TcpSocketConnectOptions) {
const { localAddress, localPort } = options;
const host = options.host || "localhost";
let { port, autoSelectFamilyAttemptTimeout, autoSelectFamily } = options;
validateStringWithoutNullBytes(host, "options.host");
if (localAddress && !isIP(localAddress)) {
throw new ERR_INVALID_IP_ADDRESS(localAddress);
}
if (localPort) {
validateNumber(localPort, "options.localPort");
}
if (typeof port !== "undefined") {
if (typeof port !== "number" && typeof port !== "string") {
throw new ERR_INVALID_ARG_TYPE(
"options.port",
["number", "string"],
port,
);
}
validatePort(port);
}
port |= 0;
if (autoSelectFamily != null) {
validateBoolean(autoSelectFamily, "options.autoSelectFamily");
} else {
autoSelectFamily = autoSelectFamilyDefault;
}
if (autoSelectFamilyAttemptTimeout !== undefined) {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Normalize before connecting: const port = rawPort ?? DEFAULT_PORT; net.connect({ port: Number(port) })
- Validate the type at the config boundary: reject port values that are neither number nor numeric string
- Use undefined (omit the field) when there is no port, never null
Example fix
// before
net.connect({ port: config.port, host }); // config.port === null -> throws
// after
net.connect({
port: config.port == null ? DEFAULT_PORT : Number(config.port),
host,
}); Defensive patterns
Strategy: validation
Validate before calling
if (port !== undefined && typeof port !== 'number' && typeof port !== 'string') {
throw new TypeError(`options.port must be number|string, got ${typeof port}`);
}
net.connect({ port: port == null ? DEFAULT_PORT : Number(port), host }); Type guard
function isValidPortValue(v: unknown): v is number | string | undefined {
return v === undefined || typeof v === 'number' || typeof v === 'string';
} Try / catch
try {
socket = net.connect({ port, host });
} catch (e: any) {
if (e?.code === 'ERR_INVALID_ARG_TYPE' && /options\.port/.test(e.message)) {
socket = net.connect({ port: DEFAULT_PORT, host });
} else throw e;
} Prevention
- Normalize optional config ports with ?? DEFAULT_PORT before passing them on
- Parse env/config ports once (Number(v)) at the boundary, not at each call site
- Use undefined for absent values — null is a type error for options.port
When it happens
Trigger: net.connect({ port: null }) from an optional config field defaulting to null; port: {} after wrong destructuring; port: true from a flag; port: 8080n (BigInt) — strings like '3000' are fine, undefined skips the check.
Common situations: JSON/YAML configs where an absent port serializes as null instead of undefined; TypeScript code assuming optional number but receiving null at runtime from an API response; env parsing that yields objects on failure.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- TLS wrap attach failed: ${attachResult}
- TLS wrap attach (JS stream) failed: ${attachResult}
- ERR_INVALID_FD_TYPE
- ERR_INVALID_IP_ADDRESS
- ERR_MISSING_ARGS
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/90fa34e43c76377a.
Report an issue: GitHub.