CloakHQ/CloakBrowser · error · Error
GeoIP resolution failed: could not discover the egress IP
Error message
GeoIP resolution failed: could not discover the egress IP
What it means
resolveProxyGeo could not determine the egress IP: neither echo services nor proxy hostname resolution returned an IP before the deadline. The library throws it because all subsequent GeoIP lookups require a concrete egress IP to map to a country/timezone.
Source
Thrown at js/src/geoip.ts:114
// timeout (a first-use ~70MB fetch legitimately outlasts it).
const dbPath = await ensureGeoipDb();
const timeoutMs = getGeoipTimeoutMs();
const deadline = deadlineFromTimeout(timeoutMs);
// Exit IP (through proxy, or the machine's own public IP when proxyUrl is
// falsy) 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.
let ip = await resolveExitIp(proxyUrl, remainingMs(deadline));
// Hostname fallback only applies to a proxy; no proxy → echo services only
if (!ip && proxyUrl && !deadlineExpired(deadline)) ip = await resolveProxyIp(proxyUrl);
if (!ip || deadlineExpired(deadline)) {
if (deadlineExpired(deadline)) {
throw new Error(`GeoIP resolution timed out after ${timeoutMs / 1000}s`);
}
throw new Error("GeoIP resolution failed: could not discover the egress IP");
}
if (!dbPath) {
throw new Error("GeoIP resolution failed: GeoIP database is unavailable");
}
try {
const buf = fs.readFileSync(dbPath);
const reader = new Reader(buf);
const result = reader.get(ip) as any;
const timezone: string | null = result?.location?.time_zone ?? null;
const countryCode: string | null = result?.country?.iso_code ?? null;
const locale =
countryCode ? (COUNTRY_LOCALE_MAP[countryCode] ?? null) : null;
return { timezone, locale, exitIp: ip };
} catch (error) {
const detail = error instanceof Error ? error.message : String(error);
throw new Error(`GeoIP lookup failed for ${ip}: ${detail}`, { cause: error });View on GitHub (pinned to d6bad5de26)
Solutions
- Check network egress and DNS: curl an echo service (e.g. ifconfig.me) from the same host/container
- Verify the proxy URL is reachable and its hostname resolves; test with curl -x <proxyUrl> https://ifconfig.me
- Increase CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS so proxy hostname resolution fits in the deadline
- Skip GeoIP resolution and pass timezone/locale explicitly if you already know them
Example fix
// before
const geo = await resolveProxyGeo({ proxyUrl, dbPath });
// after
const geo = await resolveProxyGeo({
proxyUrl,
dbPath,
timeoutMs: 30_000,
}).catch((err) => {
if (err.message.includes('egress IP')) {
return { timezone: 'UTC', locale: 'en-US', exitIp: null };
}
throw err;
}); Defensive patterns
Strategy: fallback
Validate before calling
async function canReachEgress(proxyUrl?: string): Promise<boolean> {
try {
const url = 'https://ifconfig.me';
const res = await fetch(url, proxyUrl ? { agent: new ProxyAgent(proxyUrl) } : {});
return res.ok;
} catch { return false; }
} Type guard
function isEgressDiscoveryError(e: unknown): e is Error {
return e instanceof Error && e.message.includes('could not discover the egress IP');
} Try / catch
try {
geo = await resolveProxyGeo({ proxyUrl, dbPath });
} catch (e) {
if (isEgressDiscoveryError(e)) geo = { timezone: 'UTC', locale: 'en-US', exitIp: null };
else throw e;
} Prevention
- Pre-flight an echo-service reachability check before launching the browser
- Validate proxyUrl with a quick DNS lookup of its hostname
- Set CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS generously for slow proxies
- Supply explicit timezone/locale so GeoIP is optional
When it happens
Trigger: Calling resolveProxyGeo (directly or via maybeResolveGeoip) with no reachable echo service, a proxyUrl whose hostname fails DNS resolution, or a deadline that expired mid-discovery (env CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS too small).
Common situations: Offline/sandboxed environments blocking echo endpoints, an unreachable or misconfigured proxy (typo'd host, dead upstream), DNS failures inside containers, or aggressive timeouts on slow proxy connections.
Related errors
- GeoIP resolution timed out after {timeout:0.0}s
- 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/f942db9bbea8ec7a.
Report an issue: GitHub.