denoland/deno · error · Error

${bindingName} ${errCodeMessage} ${name}

Error message

${bindingName} ${errCodeMessage} ${name}

What it means

dns.promises/resolve query() calls the native c-ares binding via this._handle[bindingName](req, toASCII(name)). If the binding returns a nonzero error code, dnsException(err, bindingName, name) builds and throws a Node-style DNS error whose message includes the binding name, the error code/message (e.g. ENOTFOUND, ESERVFAIL) and the queried name.

Source

Thrown at ext/node/polyfills/dns.ts:435

    if (isResolveCallback(options)) {
      callback = options;
      options = {};
    }

    validateString(name, "name");
    validateFunction(callback, "callback");

    const req = new QueryReqWrap();
    req.bindingName = bindingName;
    req.callback = callback as ResolveCallback;
    req.hostname = name;
    req.oncomplete = onresolve;
    req.ttl = !!(options && (options as ResolveOptions).ttl);

    const err = this._handle[bindingName](req, toASCII(name));

    if (err) {
      throw dnsException(err, bindingName, name);
    }

    return req;
  }

  ObjectDefineProperty(query, "name", {
    __proto__: null,
    value: bindingName,
  });

  return query;
}

const resolveMap = ObjectCreate(null);

class Resolver extends CallbackResolver {
  constructor(options?: ResolverOptions) {
    super(options);

View on GitHub (pinned to a961cdec3b)

Solutions

  1. Catch the error and inspect err.code (ENOTFOUND/ESERVFAIL/ECONNREFUSED) to decide between fixing the name and retrying with fallback resolvers.
  2. Retry with a public resolver via a dns.Resolver({ servers: ['8.8.8.8'] }) when the system resolver is broken.
  3. Verify the hostname spelling and that it is a name (not an IP) — resolve* APIs require hostnames; use dns.lookup for literals.
  4. Check /etc/resolv.conf and network/VPN settings if all queries fail.

Example fix

// before
const addrs = await dns.promises.resolve4('unknown.example'); // throws ENOTFOUND
// after
try {
  const addrs = await dns.promises.resolve4('unknown.example');
} catch (err) {
  if (err.code === 'ENOTFOUND') {
    const resolver = new dns.promises.Resolver({ servers: ['8.8.8.8'] });
    return resolver.resolve4('unknown.example');
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function assertResolvableName(name) {
  if (!name || typeof name !== 'string') throw new TypeError('hostname required');
  if (/^\d{1,3}(\.\d{1,3}){3}$/.test(name)) {
    throw new TypeError('use dns.lookup for IP literals, not dns.resolve*');
  }
  toASCII(name); // throws early on malformed IDN
}

Type guard

function isHostname(name) {
  return typeof name === 'string' && name.length > 0 && !net.isIP(name);
}

Try / catch

try {
  return await dns.promises.resolve4(name);
} catch (err) {
  if (err.code === 'ENOTFOUND') return []; // name does not exist
  if (['ESERVFAIL', 'ETIMEOUT', 'ECONNREFUSED'].includes(err.code)) {
    // retry with fallback resolver
    const r = new dns.promises.Resolver({ servers: ['8.8.8.8', '1.1.1.1'] });
    return r.resolve4(name);
  }
  throw err;
}

Prevention

When it happens

Trigger: dns.resolve*/dns.promises.resolve* failing synchronously at the c-ares layer — e.g. NXDOMAIN for an unknown name, SERVFAIL/timeout from resolvers, malformed internationalized names after toASCII punycode conversion, or no configured nameservers.

Common situations: Resolving a hostname that doesn't exist; DNS server outages or blocked UDP/53 in containers; resolv.conf misconfiguration; IDN names that fail punycode conversion.

Related errors


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