CloakHQ/CloakBrowser · error · Error

GeoIP lookup failed for ${ip}: ${detail}

Error message

GeoIP lookup failed for ${ip}: ${detail}

What it means

The MaxMind Reader threw while looking up the discovered egress IP; the thrown error wraps the underlying message as `GeoIP lookup failed for <ip>: <detail>`. This is a lower-level failure inside maxmind Reader.get(), not a discovery problem.

Source

Thrown at js/src/geoip.ts:132

    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 });
  }
}

function getGeoipTimeoutMs(): number {
  const raw = process.env.CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS;
  if (!raw) return DEFAULT_GEOIP_TIMEOUT_MS;
  const timeoutSeconds = Number(raw);
  if (!Number.isFinite(timeoutSeconds)) {
    console.warn(`[cloakbrowser] Invalid CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS=${raw}; using ${DEFAULT_GEOIP_TIMEOUT_MS / 1000}s`);
    return DEFAULT_GEOIP_TIMEOUT_MS;
  }
  return Math.max(timeoutSeconds, 0) * 1000;
}

function deadlineFromTimeout(timeoutMs: number): number | null {
  return timeoutMs > 0 ? performance.now() + timeoutMs : null;
}

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Re-download the GeoIP database (delete the stale file and rerun downloadGeoipDb) to fix corruption
  2. Verify the dbPath file is a valid binary mmdb (check size/magic bytes), not an HTML error page
  3. Ensure the ip value is a plain IPv4/IPv6 string (no port, scheme, or whitespace)
  4. Upgrade the maxmind package to match the database edition

Example fix

// before
const dbPath = '/tmp/geo.mmdb'; // possibly corrupt

// after
const dbPath = await downloadGeoipDb(dest).catch(async () => {
  await fs.promises.rm(dest, { force: true });
  throw new Error('GeoIP DB download failed; remove and retry');
});
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs';
function looksLikeMmdb(path: string): boolean {
  const fd = fs.openSync(path, 'r');
  const buf = Buffer.alloc(14);
  fs.readSync(fd, buf, 0, 14, 0); fs.closeSync(fd);
  return buf.toString('ascii', 12, 14) === '~~'; // mmdb metadata marker start
}

Type guard

function isGeoipLookupError(e: unknown): e is Error {
  return e instanceof Error && e.message.startsWith('GeoIP lookup failed for');
}

Try / catch

try { geo = await resolveProxyGeo({ ip, dbPath }); }
catch (e) {
  if (isGeoipLookupError(e)) {
    await fs.promises.rm(dbPath, { force: true });
    await downloadGeoipDb(dbPath);
    geo = await resolveProxyGeo({ ip, dbPath }); // retry with fresh DB
  } else throw e;
}

Prevention

When it happens

Trigger: Corrupt or truncated .mmdb file (partial download), a file that exists but is not a valid MaxMind DB, or a malformed/non-IP string passed as ip to resolveProxyGeo.

Common situations: Interrupted downloads leaving a broken .tmp/.mmdb file, wrong file passed as dbPath (e.g. an HTML error page), or version skew between the maxmind reader and the database format.

Related errors


AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28). Data as JSON: /api/errors/bcbe255fd1d14648. Report an issue: GitHub.