koala73/worldmonitor · error · Error
DNS ${recordType} lookup failed: HTTP ${response.status}
Error message
DNS ${recordType} lookup failed: HTTP ${response.status} What it means
The webhook registration DNS resolver queries Cloudflare DoH (https://cloudflare-dns.com/dns-query with Accept: application/dns-json) for A and AAAA in parallel under a 3s AbortSignal timeout; a non-2xx HTTP response from the resolver throws this error, which assertCallbackUrlRegistrationSafe then wraps as 'callbackUrl DNS resolution failed: ...'. It means the DoH service itself failed or rejected the request — not that the hostname is invalid.
Source
Thrown at server/worldmonitor/shipping/v2/webhook-shared.ts:99
return null;
}
async function defaultResolveHostname(hostname: string): Promise<string[]> {
const resolveHostnameForTest = getResolveHostnameForTest();
if (resolveHostnameForTest) return resolveHostnameForTest(hostname);
const resolveRecordType = async (recordType: 'A' | 'AAAA'): Promise<string[]> => {
const url = new URL(DNS_JSON_ENDPOINT);
url.searchParams.set('name', hostname);
url.searchParams.set('type', recordType);
const response = await fetch(url, {
headers: {
Accept: 'application/dns-json',
'User-Agent': 'WorldMonitor-ShippingV2-Webhooks/1.0',
},
signal: AbortSignal.timeout(DNS_RESOLUTION_TIMEOUT_MS),
});
if (!response.ok) throw new Error(`DNS ${recordType} lookup failed: HTTP ${response.status}`);
const data = await response.json() as { Status?: number; Answer?: Array<{ type?: number; data?: string }> };
if (data.Status !== 0) throw new Error(`DNS ${recordType} lookup failed: status ${data.Status}`);
const expectedType = recordType === 'A' ? 1 : 28;
return (data.Answer ?? [])
.filter(answer => answer.type === expectedType && typeof answer.data === 'string')
.map(answer => answer.data!);
};
const records = await Promise.all([resolveRecordType('A'), resolveRecordType('AAAA')]);
return records.flat();
}
/**
* Validate the current DNS answer before storing a webhook. Delivery makes the
* same check immediately before send and pins the resulting socket, which
* keeps this fail-fast check from becoming the only SSRF control.
*/
export async function assertCallbackUrlRegistrationSafe(
callbackUrl: string,View on GitHub (pinned to eeab0a219f)
Solutions
- Retry registration after a short backoff — DoH HTTP failures are usually transient rate limits or blips
- Verify the server runtime can reach https://cloudflare-dns.com/dns-query (egress rules, proxies)
- If deploying where DoH is unreachable, allowlist the endpoint — the resolver is not configurable outside the test Symbol override
Example fix
// before
await registerWebhook({ callbackUrl, chokepointIds }); // 400: DNS A lookup failed: HTTP 429
// after
await withRetry(() => registerWebhook({ callbackUrl, chokepointIds }), { attempts: 3, baseMs: 750 }); Defensive patterns
Strategy: retry
Try / catch
catch (e) { const desc = e?.details?.[0]?.description ?? ''; if (/DNS .* lookup failed: HTTP/.test(desc)) { retry registration with backoff — DoH HTTP failures are transient } else throw e; } Prevention
- Retry webhook registration on DNS HTTP failures with exponential backoff
- Space out bulk registrations to avoid tripping the Cloudflare DoH rate limit
- Ensure the server runtime's egress allows cloudflare-dns.com
When it happens
Trigger: Registering a webhook when Cloudflare DoH returns 429 (rate-limited) or 5xx; egress firewall/NAT/proxy blocking cloudflare-dns.com from the server runtime; a hostname malformed badly enough that DoH answers 400.
Common situations: A burst of RegisterWebhook calls tripping the DoH rate limit; restrictive egress rules in the hosting platform; a regional Cloudflare incident; corporate proxies intercepting the resolver.
Related errors
- callbackUrl DNS resolution failed: ${message}
- DNS ${recordType} lookup failed: status ${data.Status}
- callbackUrl DNS resolution returned no addresses
- callbackUrl resolves to a private/reserved address
- callbackUrl is not allowed
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/2ab0d16b7d47b0c6.
Report an issue: GitHub.