denoland/deno · error · TypeError
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
Error message
The "options" argument must be of type object or integer. Received ${actual} What it means
dns.lookup's second parameter is polymorphic: a function (treated as the callback), a number (an IP family, later validated against 0/4/6), or an object/undefined (lookup options). Any other type — string, boolean, bigint, symbol — reaches the final else-branch and throws ERR_INVALID_ARG_TYPE for 'options'.
Source
Thrown at ext/node/polyfills/dns.ts:219
let port = undefined;
// Parse arguments
if (hostname) {
validateString(hostname, "hostname");
}
if (isLookupCallback(options)) {
callback = options;
family = 0;
} else if (isFamily(options)) {
validateFunction(callback, "callback");
validateOneOf(options, "family", validFamilies);
family = options;
} else if (!isLookupOptions(options)) {
validateFunction(arguments.length === 2 ? options : callback, "callback");
throw new ERR_INVALID_ARG_TYPE("options", ["integer", "object"], options);
} else {
validateFunction(callback, "callback");
if (options?.hints != null) {
validateNumber(options.hints, "options.hints");
hints = options.hints >>> 0;
validateHints(hints);
}
if (options?.family != null) {
// Accept both numeric (0, 4, 6) and string ('IPv4', 'IPv6') family values
// to match Node.js behavior
switch (options.family) {
case "IPv4":
family = 4;
break;
case "IPv6":
family = 6;View on GitHub (pinned to 89f33cbef2)
Solutions
- Use the numeric shorthand dns.lookup(host, 4, cb) or the options object dns.lookup(host, { family: 4 }, cb)
- Coerce config-provided families: Number(family) guarded by Number.isInteger
- For 'IPv4'/'IPv6' strings, pass them inside the options object ({ family: 'IPv6' }), which the polyfill accepts
Example fix
// before
dns.lookup('example.com', 'IPv6', (err, addr) => {}); // string options -> throws
// after
dns.lookup('example.com', { family: 'IPv6' }, (err, addr) => {}); Defensive patterns
Strategy: validation
Validate before calling
// Normalize the polymorphic second arg before dns.lookup
function normalizeLookupArgs(hostname, options, callback) {
if (typeof options === 'function') return [hostname, 0, options];
if (typeof options === 'number') return [hostname, options, callback];
if (options == null || typeof options === 'object') return [hostname, options ?? {}, callback];
throw new TypeError(`bad lookup options: ${typeof options}`);
} Type guard
const isLookupOptionsLike = (v) => typeof v === 'function' || typeof v === 'number' || typeof v === 'object' || typeof v === 'undefined';
Prevention
- Pass family as a number or inside an options object — never a bare string
- Coerce config-driven families with Number() plus Number.isInteger check
- Wrap dns.lookup once in a typed helper so all call sites share the normalization
When it happens
Trigger: dns.lookup('example.com', 'IPv4', cb) (family string instead of an options object); dns.lookup(host, true, cb); dns.lookup(host, 4n, cb); passing an array of families.
Common situations: Porting getaddrinfo-style code where family was a string; config values typed as '4'/'6' strings; passing { family: 4 } correctly but passing '4' bare as the shorthand.
Related errors
- ERR_INVALID_ARG_VALUE
- ERR_MISSING_ARGS
- fetch failed
- Invalid port: '${maybePort}'
- Invalid port: ${maybePort}
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/b20d69de58ea1cde.
Report an issue: GitHub.