CloakHQ/CloakBrowser · error · InvalidOperationException
GeoIP resolution timed out after {timeout:0.0}s
Error message
GeoIP resolution timed out after {timeout:0.0}s What it means
The GeoIP resolver could not determine the proxy/browser egress IP before the caller-supplied deadline elapsed. Because all downstream GeoIP lookups need an IP, the library aborts with a timeout error. It is a wrapper condition: any slow echo-service or DNS resolution that overshoots the deadline triggers it.
Source
Thrown at dotnet/src/CloakBrowser/GeoIp.cs:119
// timeout (a first-use ~70MB fetch legitimately outlasts it).
var dbPath = await EnsureGeoIpDbAsync(ct).ConfigureAwait(false);
var timeout = GetGeoIpTimeoutSeconds();
var deadline = DeadlineFromTimeout(timeout);
// Exit IP (through proxy, or the machine's own public IP when proxyUrl is
// null/empty) is most accurate - gateway DNS may differ from exit. Resolved
// even when the DB is unavailable: the IP does not need the DB, and dropping
// it on a DB hiccup would let WebRTC fall back to the real IP behind a proxy
// while the connection shows the proxy IP - a real deanonymization.
var ip = await ResolveExitIpAsync(proxyUrl, RemainingSeconds(deadline), ct).ConfigureAwait(false);
// Hostname fallback only applies to a proxy; no proxy -> echo services only.
if (ip == null && !string.IsNullOrEmpty(proxyUrl) && !DeadlineExpired(deadline))
ip = ResolveProxyIp(proxyUrl);
if (ip == null || DeadlineExpired(deadline))
{
if (deadline != null && DeadlineExpired(deadline))
throw new InvalidOperationException($"GeoIP resolution timed out after {timeout:0.0}s");
throw new InvalidOperationException("GeoIP resolution failed: could not discover the egress IP");
}
if (dbPath == null)
throw new InvalidOperationException("GeoIP resolution failed: GeoIP database is unavailable");
try
{
using var reader = new DatabaseReader(dbPath);
var resp = reader.City(ip);
var timezone = resp.Location?.TimeZone;
var country = resp.Country?.IsoCode;
string? locale = country != null && CountryLocaleMap.TryGetValue(country, out var l) ? l : null;
CloakLog.Debug("GeoIP: {0} -> tz={1}, country={2}, locale={3}", ip, timezone, country, locale);
return (timezone, locale, ip);
}
catch (Exception exc)
{View on GitHub (pinned to d6bad5de26)
Solutions
- Increase the GeoIP resolution timeout/deadline passed to the API.
- Verify the proxy URL is reachable and that IP echo services (e.g. api.ipify-style endpoints) are not firewalled.
- Pre-resolve or cache the egress IP and pass it in (or skip GeoIP) when operating in restricted networks.
- If DNS on the proxy host is the bottleneck, warm it up or pass a pre-resolved IP.
Example fix
// before var geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl, timeout: TimeSpan.FromSeconds(1)); // after var geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl, timeout: TimeSpan.FromSeconds(10)); // or skip geo resolution entirely on locked-down networks // var geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl, timeout: Timeout.InfiniteTimeSpan, skipOnTimeout: true);
Defensive patterns
Strategy: retry
Validate before calling
var sw = Stopwatch.StartNew();
if (!await Network.CanReachAsync("https://api.ipify.org"))
geoTimeout = TimeSpan.FromSeconds(30); // be generous on restricted networks Try / catch
catch (InvalidOperationException ex) when (ex.Message.Contains("GeoIP resolution timed out"))
{
geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl, timeout: TimeSpan.FromSeconds(30)); // retry with a larger budget
} Prevention
- Size the GeoIP deadline relative to worst-case echo-service latency (>=5-10s on proxied networks).
- Verify proxy reachability before starting GeoIP resolution.
- Cache the resolved egress IP across calls when the proxy is stable.
When it happens
Trigger: Calling ResolveProxyGeoAsync / MaybeResolveGeoIpAsync / Collect with a short timeout (the deadline param) while the egress-IP echo services or ResolveProxyIp(proxyUrl) DNS lookup are slow, blocked, or the proxy is unreachable — DeadlineExpired(deadline) is true after the discovery attempts.
Common situations: Corporate firewalls blocking IP echo endpoints; slow or dead proxies making every probe hang until the deadline; timeouts tuned too aggressively (sub-second); IPv6-only environments where echo services fail; captive-portal networks.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- GeoIP resolution failed: could not discover the egress IP
- GeoIP resolution failed: could not discover the egress IP
- GeoIP resolution failed: GeoIP database is unavailable
- GeoIP lookup failed for ${ip}: ${detail}
- HTTP ${response.status}
AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28).
Data as JSON: /api/errors/7f0f302967bab80d.
Report an issue: GitHub.