koala73/worldmonitor · error · Error

Webhook URL DNS resolution returned no addresses

Error message

Webhook URL DNS resolution returned no addresses

What it means

Thrown when the DoH resolution call succeeded (no exception) but returned zero A/AAAA records for the hostname — effectively an NXDOMAIN or a domain with no address records. Registration refuses such hostnames because there is no address to SSRF-check or deliver to.

Source

Thrown at api/_notification-webhook-ssrf.ts:234

 * connection) because DNS can change after registration.
 */
export async function assertNotificationWebhookRegistrationUrlSafe(
  rawUrl: string,
  resolveHostname: ResolveHostname = defaultResolveHostname,
): Promise<void> {
  const staticError = blockedNotificationWebhookUrlReason(rawUrl);
  if (staticError) throw new Error(staticError);

  const hostname = new URL(rawUrl).hostname.toLowerCase();
  if (isIpLiteral(hostname)) return;
  let resolvedAddresses: string[];
  try {
    resolvedAddresses = await resolveHostname(hostname);
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    throw new Error(`Webhook URL DNS resolution failed: ${message}`);
  }
  if (!resolvedAddresses.length) throw new Error('Webhook URL DNS resolution returned no addresses');
  if (resolvedAddresses.some(isBlockedNotificationResolvedAddress)) {
    throw new Error('Webhook URL must not point to a private/local address');
  }
}

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Double-check the hostname spelling and the domain's registration status.
  2. Confirm the host has at least one A or AAAA record: `dig +short A <host>` and `dig +short AAAA <host>`.
  3. Provision DNS for the host (add an A/AAAA record at your DNS provider) and retry registration.
  4. If the host is a CNAME, ensure the target chain terminates in an address record.

Example fix

// before
registerWebhook('https://typo.exmaple.com/hook')
// after
registerWebhook('https://hook.example.com/hook')
Defensive patterns

Strategy: validation

Validate before calling

async function hostHasAddressRecord(hostname: string): Promise<boolean> {
  // Mirror the production resolver (DoH A+AAAA).
  const r = await fetch(`https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(hostname)}&type=A`, {
    headers: { Accept: 'application/dns-json' },
    signal: AbortSignal.timeout(2000),
  });
  const data = await r.json();
  return Array.isArray(data?.Answer) && data.Answer.some(a => a?.type === 1);
}

Try / catch

try {
  await assertNotificationWebhookRegistrationUrlSafe(rawUrl);
} catch (err) {
  if (err.message === 'Webhook URL DNS resolution returned no addresses') {
    return res.status(400).json({ error: 'The webhook host has no DNS address record.' });
  }
  throw err;
}

Prevention

When it happens

Trigger: Webhook registration with a hostname that legitimately does not exist, has only CNAME/MX records but no A/AAAA, was decommissioned, or was typo'd. Also reached when a CNAME flattens to nothing.

Common situations: Typo in the webhook host (e.g. `https://hook.exmaple.com/`); a domain whose DNS is not yet provisioned; a domain that only has MX records; a recently expired/de-registered domain.

Understand the failure class

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/f0f7f8da7244c3b2. Report an issue: GitHub.