{"record":{"id":"69902c48a0c5f312","repo":"agalwood/Motrix","slug":"geoipsourceunsupported","errorCode":"GeoIPSourceUnsupported","errorMessage":"MaxMind official source is not yet supported (Phase 2.1).","messagePattern":"MaxMind official source is not yet supported \\(Phase 2\\.1\\)\\.","errorType":"error_code","errorClass":"AppError","httpStatus":null,"severity":"warning","filePath":"src/core/geoip/geo-ip-manager.ts","lineNumber":176,"sourceCode":"    if (Date.now() - s.lastUpdatedAt < intervalMs) return\n    if (this.isDownloading) return\n    log.info({ source: s.source }, 'GeoIP auto-update due')\n    await this.triggerUpdate().catch(() => {\n      // Errors already recorded in lastError + status event.\n    })\n  }\n\n  private async runUpdate(): Promise<GeoIPStatus> {\n    const settings = this.getSettings()\n    const url = resolveDownloadUrl(settings)\n    if (!url) {\n      const message =\n        settings.source === 'maxmind'\n          ? 'MaxMind official source is not yet supported (Phase 2.1).'\n          : 'No download URL configured for the selected source.'\n      this.lastError = message\n      this.emitStatus()\n      throw new AppError(ErrorCode.GeoIPSourceUnsupported, message)\n    }\n\n    this.isDownloading = true\n    this.lastError = null\n    this.emitStatus()\n\n    const onProgress: ProgressListener = (progress) => {\n      this.eventBus.emit(Events.GeoIPUpdateProgress, progress)\n    }\n\n    try {\n      const result = await this.downloader.download(\n        url,\n        this.dbPath,\n        onProgress\n      )\n      await this.service.reload(this.dbPath)\n      this.currentSizeBytes = result.sizeBytes","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/geoip/geo-ip-manager.ts#L158-L194","documentation":"Thrown by the GeoIP manager when the configured source is 'maxmind' but resolveDownloadUrl(settings) returns no usable URL — the official MaxMind source requires an account/license key and is explicitly marked unimplemented (Phase 2.1). The manager stores the message as lastError, emits status, and throws GeoIPSourceUnsupported.","triggerScenarios":"runUpdate() is called with settings.source === 'maxmind'. resolveDownloadUrl returns null/undefined because the MaxMind path is not yet wired up, so the unsupported-source branch is taken.","commonSituations":"A user or config preset selected the MaxMind source before the integration shipped; an old config persisted 'maxmind' as the source after an upgrade/downgrade; a defaults file sets maxmind as the preferred source.","solutions":["Switch the GeoIP source to a supported mirror (e.g. the default free GeoLite mirror) until MaxMind support ships.","In settings, set geoip.source away from 'maxmind'.","Provide a license key + host URL only once the MaxMind integration is implemented (track Phase 2.1).","Reset GeoIP settings to defaults to clear the stale 'maxmind' selection."],"exampleFix":"// before\nconst url = resolveDownloadUrl(settings)\nif (!url) {\n  const message = settings.source === 'maxmind' ? 'MaxMind official source is not yet supported (Phase 2.1).' : 'No download URL configured for the selected source.'\n  throw new AppError(ErrorCode.GeoIPSourceUnsupported, message)\n}\n\n// after — fail fast at settings time so users cannot select an unsupported source\nif (settings.source === 'maxmind') {\n  throw new AppError(ErrorCode.GeoIPSourceUnsupported, 'MaxMind official source is not yet supported (Phase 2.1). Use a supported mirror.')\n}","handlingStrategy":"validation","validationCode":"// Reject unsupported sources at settings time, before runUpdate is ever called.\nfunction assertGeoIpSourceSupported(source: string) {\n  if (source === 'maxmind') {\n    throw new AppError(ErrorCode.GeoIPSourceUnsupported, 'MaxMind official source is not yet supported (Phase 2.1).')\n  }\n}","typeGuard":"const SUPPORTED_SOURCES = new Set(['mirror', 'custom' /* ...actual supported values */ ])\nfunction isSupportedSource(s: string): s is (typeof SUPPORTED_SOURCES extends Set<infer T> ? T : never) {\n  return SUPPORTED_SOURCES.has(s)\n}","tryCatchPattern":"try {\n  await manager.update()\n} catch (err) {\n  if (err instanceof AppError && err.code === ErrorCode.GeoIPSourceUnsupported && /MaxMind/.test(err.message)) {\n    // switch source to a supported mirror in settings, then retry\n  } else throw err\n}","preventionTips":["Do not expose the MaxMind option in the UI until Phase 2.1 ships.","Reset GeoIP settings to defaults after upgrades.","Validate source against a whitelist at settings-write time."],"tags":["geoip","config","unsupported-feature","maxmind"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}