Kareadita/Kavita · warning · KavitaException

url-unable-to-resolve

Error message

url-unable-to-resolve

What it means

Thrown by UrlValidationService.ValidateUrlAsync when Dns.GetHostAddressesAsync(uri.Host) raises a SocketException — the hostname cannot be resolved. This is the DNS-resolution step of the SSRF gate, performed after the URI is parsed and the scheme is verified. It is a localized KavitaException surfaced as HTTP 500 (or 400 where the caller wraps it).

Source

Thrown at Kavita.Services/UrlValidationService.cs:32

    {
        if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
        {
            throw new KavitaException(await localizationService.TranslateAsync("url-malformed"));
        }

        if (!string.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
        {
            throw new KavitaException(await localizationService.TranslateAsync("url-https-only"));
        }

        IPAddress[] addresses;
        try
        {
            addresses = await Dns.GetHostAddressesAsync(uri.Host);
        }
        catch (SocketException)
        {
            throw new KavitaException(await localizationService.TranslateAsync("url-unable-to-resolve"));
        }

        if (addresses.Length == 0)
        {
            throw new KavitaException(await localizationService.TranslateAsync("url-unable-to-resolve"));
        }

        foreach (var address in addresses)
        {
            if (IpBlocklist.IsBlockedAddress(address))
            {
                throw new KavitaException(await localizationService.TranslateAsync("url-blocked-address"));
            }
        }
    }
}

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Verify the hostname resolves from the Kavita server itself (`nslookup host` / `dig host` in the container).
  2. Correct typos and ensure the host is publicly resolvable if Kavita runs in a restricted network.
  3. Configure the container/host DNS (e.g., /etc/resolv.conf or Docker dns:) to reach a resolver that can answer for the target.

Example fix

// before
validate(url: string) { /* none */ }
// after
validate(url: string) {
  const host = new URL(url).hostname;
  // best-effort client hint; server DNS is authoritative
  if (!host.includes('.')) return throwError(() => new Error('Hostname looks invalid'));
  return of(true);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// best-effort client check; the server's DNS is authoritative
function looksResolvableHost(url: string): boolean {
  try { const h = new URL(url).hostname; return h.includes('.') && !/\s/.test(h); } catch { return false; }
}

Try / catch

try { await svc.fetchFromUrl(url); } catch (e) { if (/resolve/i.test(e.message)) showUser('Hostname could not be resolved; check the address or server DNS'); else throw e; }

Prevention

When it happens

Trigger: ValidateUrlAsync receives a well-formed https URL whose host does not resolve (NXDOMAIN, transient DNS failure, or no network). Reachable from cover/favicon/font/CBL/upload callers.

Common situations: Typo in the hostname; the Kavita server's DNS cannot reach the public resolver (split-horizon DNS, container DNS misconfig); the host is an internal-only name not resolvable from the server; temporary DNS outage.

Related errors


AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13). Data as JSON: /api/errors/20b84aab27771c0d. Report an issue: GitHub.