louislam/uptime-kuma · error · Error

DNS lookup returned no addresses

Error message

DNS lookup returned no addresses

What it means

Thrown inside resolveSteamHostname() when dns.lookup resolved without throwing but produced no usable address. The code finds the first IPv4 address (preferred) and falls back to addresses[0].address; if both are undefined, no address can be handed to the Steam addr filter. This is a defensive guard against an empty/oddly-shaped lookup result.

Source

Thrown at server/monitor-types/steam.js:122

    /**
     * Resolves hostnames before passing them to Steam's addr filter.
     * @param {string} hostname Steam server hostname or IP address.
     * @returns {Promise<string>} IP address accepted by the Steam API.
     * @throws {Error} When the hostname cannot be resolved.
     */
    async resolveSteamHostname(hostname) {
        if (net.isIP(hostname)) {
            return hostname;
        }

        try {
            const lookupResult = await this.lookup(hostname, { all: true });
            const addresses = Array.isArray(lookupResult) ? lookupResult : [lookupResult];
            const ipv4Address = addresses.find(({ address }) => net.isIP(address) === 4);
            const resolvedAddress = ipv4Address?.address || addresses[0]?.address;

            if (!resolvedAddress) {
                throw new Error("DNS lookup returned no addresses");
            }

            return resolvedAddress;
        } catch (error) {
            throw new Error(`Unable to resolve Steam server hostname "${hostname}": ${error.message}`);
        }
    }
}

module.exports = {
    SteamMonitorType,
};

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Resolve the hostname with 'dig' or 'nslookup' on the Uptime-Kuma host and confirm at least one A or AAAA record is returned.
  2. If the server only has IPv6, ensure the resolver returns AAAA records with the expected shape (address field).
  3. Replace the monitor hostname with the server's literal IP address to bypass DNS entirely.
  4. In tests, ensure the injected lookup returns objects shaped like { address: '1.2.3.4', family: 4 }.
Defensive patterns

Strategy: validation

Validate before calling

function pickAddress(lookupResult) {
  const addrs = Array.isArray(lookupResult) ? lookupResult : [lookupResult];
  const ipv4 = addrs.find(a => net.isIP(a.address) === 4);
  const chosen = ipv4?.address || addrs[0]?.address;
  if (!chosen) throw new Error("DNS lookup returned no addresses");
  return chosen;
}

Type guard

function hasUsableAddress(entries) { return Array.isArray(entries) && entries.some(e => e && typeof e.address === "string" && net.isIP(e.address)); }

Try / catch

const resolved = pickAddress(await this.lookup(hostname, { all: true }));

Prevention

When it happens

Trigger: Produced when the lookup returns an array whose entries lack an 'address' field, or returns an empty array (some custom lookup stubs or DNS configurations can do this), and net.isIP did not short-circuit because the input was a hostname rather than a literal IP.

Common situations: Custom DNS resolver returning malformed records; hostname exists only as a CNAME loop with no A/AAAA; transient empty response from a flaky resolver; test stub providing a lookup result missing the expected 'address' property; IPv6-only host where the find() for IPv4 fails and the fallback entry shape differs.

Understand the failure class

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/9d6b7acc77b4cf67. Report an issue: GitHub.