denoland/deno · error · TypeError

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The argument 'address' is invalid. Received ${address}

What it means

lookupService() requires address to be a literal IPv4 or IPv6 string: it is validated with isIP(), and isIP(address) === 0 throws ERR_INVALID_ARG_VALUE. The API only does reverse (getnameinfo) resolution - forward-resolving a hostname like 'localhost' is not supported here.

Source

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

    req.oncomplete = onlookupservice;
    req.resolve = resolve;
    req.reject = reject;

    const errCode = cares.getnameinfo(req, address, port);

    if (errCode) {
      reject(dnsException(errCode, "getnameinfo", address));
    }
  });
}

function lookupService(address: string, port: number) {
  if (arguments.length !== 2) {
    throw new ERR_MISSING_ARGS("address", "port");
  }

  if (isIP(address) === 0) {
    throw new ERR_INVALID_ARG_VALUE("address", address);
  }

  port = validatePort(port);

  return createLookupServicePromise(address, port);
}

function createResolverPromise(
  resolver: Resolver,
  bindingName: string,
  hostname: string,
  ttl: boolean,
) {
  return new Promise((resolve, reject) => {
    const req = new QueryReqWrap();

    req.bindingName = bindingName;
    req.hostname = hostname;

View on GitHub (pinned to a961cdec3b)

Solutions

  1. Resolve names first: const { address } = await dnsPromises.lookup(hostname), then lookupService(address, port).
  2. Pre-check with net.isIP(address) !== 0 and reject early.
  3. Normalize socket-style IPv6 (strip brackets) before calling.

Example fix

// before
await dnsPromises.lookupService('localhost', 80);

// after
const { address } = await dnsPromises.lookup('localhost');
await dnsPromises.lookupService(address, 80);
Defensive patterns

Strategy: validation

Validate before calling

import { isIP } from 'node:net';

async function toIpLiteral(address) {
  if (isIP(address) !== 0) return address;
  const { address: resolved } = await dns.promises.lookup(address);
  return resolved;
}
const { hostname, service } = await dnsPromises.lookupService(await toIpLiteral(addr), port);

Type guard

import { isIP } from 'node:net';
const isIpLiteral = (s) => typeof s === 'string' && isIP(s) !== 0;

Try / catch

try {
  await dnsPromises.lookupService(address, port);
} catch (err) {
  if (err?.code === 'ERR_INVALID_ARG_VALUE' && err.message.includes('address')) {
    const r = await dnsPromises.lookup(address);
    return dnsPromises.lookupService(r.address, port);
  }
  throw err;
}

Prevention

When it happens

Trigger: lookupService('localhost', 80); lookupService('example.com', 443); an empty string; or a URL/origin string like 'https://1.2.3.4:80' passed as the address.

Common situations: Passing peer hostnames that upstream code already resolved; feeding URL origins or host:port strings into an API that wants a bare IP; IPv6 values still wrapped in brackets.

Related errors


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