{"record":{"id":"38732ab512554c76","repo":"CloakHQ/CloakBrowser","slug":"geoip-resolution-failed-geoip-database-is-unavail-38732a","errorCode":null,"errorMessage":"GeoIP resolution failed: GeoIP database is unavailable","messagePattern":"GeoIP resolution failed: GeoIP database is unavailable","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/GeoIp.cs","lineNumber":124,"sourceCode":"\n        // Exit IP (through proxy, or the machine's own public IP when proxyUrl is\n        // null/empty) is most accurate - gateway DNS may differ from exit. Resolved\n        // even when the DB is unavailable: the IP does not need the DB, and dropping\n        // it on a DB hiccup would let WebRTC fall back to the real IP behind a proxy\n        // while the connection shows the proxy IP - a real deanonymization.\n        var ip = await ResolveExitIpAsync(proxyUrl, RemainingSeconds(deadline), ct).ConfigureAwait(false);\n        // Hostname fallback only applies to a proxy; no proxy -> echo services only.\n        if (ip == null && !string.IsNullOrEmpty(proxyUrl) && !DeadlineExpired(deadline))\n            ip = ResolveProxyIp(proxyUrl);\n        if (ip == null || DeadlineExpired(deadline))\n        {\n            if (deadline != null && DeadlineExpired(deadline))\n                throw new InvalidOperationException($\"GeoIP resolution timed out after {timeout:0.0}s\");\n            throw new InvalidOperationException(\"GeoIP resolution failed: could not discover the egress IP\");\n        }\n\n        if (dbPath == null)\n            throw new InvalidOperationException(\"GeoIP resolution failed: GeoIP database is unavailable\");\n\n        try\n        {\n            using var reader = new DatabaseReader(dbPath);\n            var resp = reader.City(ip);\n            var timezone = resp.Location?.TimeZone;\n            var country = resp.Country?.IsoCode;\n            string? locale = country != null && CountryLocaleMap.TryGetValue(country, out var l) ? l : null;\n            CloakLog.Debug(\"GeoIP: {0} -> tz={1}, country={2}, locale={3}\", ip, timezone, country, locale);\n            return (timezone, locale, ip);\n        }\n        catch (Exception exc)\n        {\n            throw new InvalidOperationException($\"GeoIP lookup failed for {ip}: {exc.Message}\", exc);\n        }\n    }\n\n    // -----------------------------------------------------------------------","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/GeoIp.cs#L106-L142","documentation":"An egress IP was discovered, but the resolver could not locate a MaxMind GeoIP database file on disk (dbPath == null), so the city/timezone lookup cannot run. The library ships or downloads this database lazily, and this error means that acquisition/lookup failed. It is an environment/setup problem, not a network-egress one.","triggerScenarios":"Calling ResolveProxyGeoAsync / MaybeResolveGeoIpAsync / Collect after egress IP discovery succeeded, when the GeoIP database path lookup returned null — database never downloaded, deleted from the cache directory, moved, or failed to initialize.","commonSituations":"First run in an offline environment where the MaxMind DB download failed silently; antivirus or cleanup tools deleting the .mmdb cache file; container images built without the GeoIP database; a broken or relocated cache directory after an upgrade.","solutions":["Ensure outbound access to the GeoIP database source on first run so it can download, then retry.","Check the cache/data directory for the .mmdb file and restore or re-download it manually.","Verify the library's data-directory configuration points to a writable, persistent location.","If GeoIP data is not needed, use the code path that skips GeoIP resolution."],"exampleFix":"// before\nvar geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl); // throws: db unavailable\n\n// after\nif (GeoIp.IsDatabaseAvailable())\n    var geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl);\nelse\n    await GeoIp.EnsureDatabaseAsync(ct); // fetch/reinstall the MaxMind db first","handlingStrategy":"validation","validationCode":"if (!GeoIp.IsDatabaseAvailable())\n    await GeoIp.EnsureDatabaseAsync(ct); // download/repair the .mmdb before resolving","typeGuard":null,"tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"GeoIP database is unavailable\"))\n{\n    await GeoIp.EnsureDatabaseAsync(default);\n    geo = await browser.GeoIp.ResolveProxyGeoAsync(proxyUrl); // retry once\n}","preventionTips":["Pin the GeoIP database in your container/image build.","Keep the data directory persistent and excluded from cleanup jobs.","Verify the .mmdb file exists and is non-zero size at startup."],"tags":["geoip","maxmind","database","setup","filesystem"],"backgroundTag":"missing-data-file","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}