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
- Verify connectivity to the configured GeoIP download URL (curl -I <url>) from the same host.
- Increase options.timeoutMs to accommodate slow links.
- Check DNS resolution for the host and fix /etc/hosts or resolver config if it fails.
- If behind a proxy, ensure HTTP(S)_PROXY env vars are set so fetch uses them.
- 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
- Configure reasonable timeoutMs (e.g. 30s+) for slow links.
- Ensure HTTP(S)_PROXY env vars are set behind corporate proxies.
- Validate DNS for the GeoIP host before scheduling updates.
- Schedule retries with backoff for transient network errors.
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
- GeoIPDatabaseInvalid
- plugin.http.timeout
- transient-failure
- EngineProcessTerminationFailed
- GeoIPSourceUnsupported
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/838de3d2ff74a17f.
Report an issue: GitHub.