agalwood/Motrix · error · AppError

GeoIPDownloadFailed

GeoIPDownloadFailed

Error message

network error: ${(err as Error).message}

What it means

Thrown by the GeoIP database downloader when the underlying fetch() rejects. Any network-layer failure — DNS resolution error, connection refused/reset, TLS handshake failure, or an AbortController timeout firing — surfaces here as GeoIPDownloadFailed with the original error chained as the cause. The downloader treats the request as never having reached a valid HTTP response.

Source

Thrown at src/core/geoip/geo-ip-downloader.ts:59

    onProgress?: ProgressListener
  ): Promise<DownloadResult> {
    await mkdir(path.dirname(dbPath), { recursive: true })

    const controller = new AbortController()
    const timeoutId = setTimeout(
      () => controller.abort(),
      this.options.timeoutMs
    )

    let response: Response
    try {
      response = await fetch(url, {
        signal: controller.signal,
        redirect: 'follow',
      })
    } catch (err) {
      clearTimeout(timeoutId)
      throw new AppError(
        ErrorCode.GeoIPDownloadFailed,
        `network error: ${(err as Error).message}`,
        err
      )
    }

    if (!response.ok) {
      clearTimeout(timeoutId)
      throw new AppError(
        ErrorCode.GeoIPDownloadFailed,
        `http ${response.status} ${response.statusText} for ${url}`
      )
    }

    const totalHeader = response.headers.get('content-length')
    const bytesTotal = totalHeader ? Number.parseInt(totalHeader, 10) : -1
    const version = deriveVersion(response.headers)

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Verify connectivity to the configured GeoIP download URL (curl -I <url>) from the same host.
  2. Increase options.timeoutMs to accommodate slow links.
  3. Check DNS resolution for the host and fix /etc/hosts or resolver config if it fails.
  4. If behind a proxy, ensure HTTP(S)_PROXY env vars are set so fetch uses them.
  5. Retry the update — transient network blips are common and the manager supports re-running runUpdate().

Example fix

// before
try {
  response = await fetch(url, { signal: controller.signal, redirect: 'follow' })
} catch (err) {
  throw new AppError(ErrorCode.GeoIPDownloadFailed, `network error: ${(err as Error).message}`, err)
}

// after — distinguish abort/timeout from genuine network errors for the caller
} catch (err) {
  clearTimeout(timeoutId)
  const aborted = (err as Error).name === 'AbortError'
  throw new AppError(
    ErrorCode.GeoIPDownloadFailed,
    aborted ? `download timed out after ${this.options.timeoutMs}ms` : `network error: ${(err as Error).message}`,
    err
  )
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight connectivity check (best-effort; not authoritative).
async function geoIpReachable(url: string, timeoutMs: number): Promise<boolean> {
  try {
    const ctrl = new AbortController()
    const t = setTimeout(() => ctrl.abort(), timeoutMs)
    await fetch(url, { method: 'HEAD', signal: ctrl.signal })
    clearTimeout(t)
    return true
  } catch { return false }
}

Try / catch

for (const delay of [0, 1000, 5000]) {
  try {
    return await downloader.download(...)
  } catch (err) {
    if (err instanceof AppError && err.code === ErrorCode.GeoIPDownloadFailed && /network error/.test(err.message) && delay < 5000) {
      await new Promise(r => setTimeout(r, delay))
      continue
    }
    throw err
  }
}

Prevention

When it happens

Trigger: fetch(url, { signal, redirect: 'follow' }) throws. Specifically: DNS failure on the GeoIP CDN host; TCP connection refused/reset; TLS certificate error; the timeout set via setTimeout+controller.abort() fires before a response; the user is offline.

Common situations: No internet connectivity; corporate proxy/MITM blocking the CDN; the GeoIP host DNS is misconfigured; timeoutMs is set too low for a slow connection; an expired/blocked CA chain causes TLS failure; firewall egress blocked.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/838de3d2ff74a17f. Report an issue: GitHub.