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 ${options}

What it means

dns.promises.lookup() accepts options as either an integer IP family or an options object (hints, family, all, order, ...). The polyfill tests options with isFamily() (integer, then validated against validFamilies) and isLookupOptions() (options-object shape); anything else - strings, booleans, arrays, null - throws ERR_INVALID_ARG_TYPE listing ['integer', 'object'].

Source

Thrown at ext/node/polyfills/internal/dns/promises.ts:192

function lookup(
  hostname: string,
  options: unknown,
): Promise<void | LookupAddress | LookupAddress[]> {
  let hints = 0;
  let family = 0;
  let all = false;
  let dnsOrder = getDefaultDnsOrder();

  // Parse arguments
  if (hostname) {
    validateString(hostname, "hostname");
  }

  if (isFamily(options)) {
    validateOneOf(options, "family", validFamilies);
    family = options;
  } else if (!isLookupOptions(options)) {
    throw new ERR_INVALID_ARG_TYPE("options", ["integer", "object"], options);
  } else {
    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;
          break;
        default:

View on GitHub (pinned to a961cdec3b)

Solutions

  1. Pass the object form: dnsPromises.lookup(host, { family: 4 }).
  2. Coerce config values once at startup: family = Number(family), then wrap into the options object.
  3. Reject non-integer/non-object option values at the boundary with an isFamilyOrOptions guard.

Example fix

// before
dnsPromises.lookup(host, '4'); // family as string

// after
dnsPromises.lookup(host, { family: 4 });
// or: dnsPromises.lookup(host, 4);
Defensive patterns

Strategy: validation

Validate before calling

function normalizeLookupOptions(o) {
  if (o === undefined) return undefined;
  if (Number.isInteger(o) && [0, 4, 6].includes(o)) return o;
  if (typeof o === 'object' && o !== null && !Array.isArray(o)) return o;
  throw new TypeError('options must be an integer family or an options object');
}
await dns.promises.lookup(host, normalizeLookupOptions(opts));

Type guard

const isFamilyOrOptions = (o) =>
  (Number.isInteger(o) && [0, 4, 6].includes(o)) ||
  (typeof o === 'object' && o !== null && !Array.isArray(o));

Try / catch

try {
  await dnsPromises.lookup(host, opts);
} catch (err) {
  if (err?.code === 'ERR_INVALID_ARG_TYPE' && err.message.includes('options')) {
    return dnsPromises.lookup(host, {});
  }
  throw err;
}

Prevention

When it happens

Trigger: dnsPromises.lookup('example.com', '4') or 'ipv6' (family as a string); lookup(host, ['A']); lookup(host, true); passing a parsed URL object as options.

Common situations: Config files that store family as text; env-var-driven options coerced to strings; code copied from dns.resolve()-style APIs where the second argument is a record-type string.

Related errors


AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20). Data as JSON: /api/errors/dd71df38cccb835d. Report an issue: GitHub.