Skip to content

fix: prevent Country Brief modal from getting stuck on geocode failure#1134

Merged
koala73 merged 1 commit intokoala73:mainfrom
NewCoder3294:fix/country-brief-geocode-stuck-loading
Mar 6, 2026
Merged

fix: prevent Country Brief modal from getting stuck on geocode failure#1134
koala73 merged 1 commit intokoala73:mainfrom
NewCoder3294:fix/country-brief-geocode-stuck-loading

Conversation

@NewCoder3294
Copy link
Contributor

Summary

Fixes #1133 — the Country Brief modal could get permanently stuck on "Identifying…" / "Locating…" when the reverse geocode request fails, times out, or is aborted.

Three layers of defense:

  • 8-second timeout on the Nominatim reverse geocode fetch so the request can never hang indefinitely. Abort/timeout errors are intentionally not cached so Retry works.
  • Error state UI with a clear message ("Could not identify a country at this location") plus Retry and Close buttons, replacing the previous silent-close behavior.
  • Guard refreshOpenBrief() against the __error__ sentinel code to prevent unnecessary processing while the error state is displayed.

Files changed

File Change
src/utils/reverse-geocode.ts Add timeout + AbortSignal support
src/app/country-intel.ts Show error state instead of silent hide; guard __error__
src/components/CountryBriefPanel.ts Add showGeoError to interface
src/components/CountryDeepDivePanel.ts Implement showGeoError (deep dive panel)
src/components/CountryBriefPage.ts Implement showGeoError (overlay panel)
src/styles/country-deep-dive.css CSS for error state (deep dive)
src/styles/main.css CSS for error state (overlay)
src/locales/*.json (21 files) i18n strings for all locales

Test plan

  • Open the map/globe view
  • Click on an ocean area (no country geometry) to trigger reverse geocoding
  • In DevTools Network tab, block nominatim.openstreetmap.org requests
  • Verify the error state appears after ~8s with the message + Retry/Close buttons
  • Unblock the network → click Retry → verify it resolves normally
  • Click Close → verify the modal dismisses and the map resumes rendering
  • Verify normal country clicks still work correctly
  • Verify tsc --noEmit and vite build pass cleanly

🤖 Generated with Claude Code

When a user clicks on the map where no country geometry exists (ocean,
ambiguous border), reverse geocoding via Nominatim is used. If this
request fails, times out, or is aborted, the modal could remain stuck
on "Identifying…" / "Locating…" with no feedback and no way to dismiss.

Three layers of defense:

1. Add 8-second timeout to the reverse geocode fetch so it cannot hang
   indefinitely. Abort/timeout errors are not cached so retry works.

2. Replace silent modal close with an error state showing a clear
   message ("Could not identify a country at this location") plus
   Retry and Close buttons.

3. Guard refreshOpenBrief() against the __error__ sentinel code.

i18n strings added for all 21 locales.

Closes koala73#1133

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 6, 2026

@NewCoder3294 is attempting to deploy a commit to the Elie Team on Vercel.

A member of the Team first needs to authorize it.

@koala73 koala73 merged commit e9050bb into koala73:main Mar 6, 2026
1 of 2 checks passed
koala73 added a commit that referenced this pull request Mar 6, 2026
The geocodeFailed, retryBtn, and closeBtn keys were inserted at the
wrong nesting level in nl.json, pt.json, and sv.json — siblings of
countryIntel instead of children. Fixes i18n lookup for Dutch,
Portuguese, and Swedish users.

Follow-up to #1134.
koala73 added a commit that referenced this pull request Mar 7, 2026
Reverts files to main versions where old branch changes would
overwrite intentional fixes from PRs #1134, #1138, #1144, #1154:

- news/_shared.ts: keep gemini-2.5-flash model (not stale gpt-oss)
- redis.ts: keep seed-meta throttle from PR #1138
- reverse-geocode.ts: keep AbortController timeout from PR #1134
- CountryBriefPage.ts: keep showGeoError() from PR #1134
- country-intel.ts: keep showGeoError usage from PR #1134
- get-risk-scores.ts: revert non-existent imports
- watchlist.ts: keep DXB/RUH airports from PR #1144
- locales: restore geocodeFailed/retryBtn/closeBtn keys
koala73 added a commit that referenced this pull request Mar 7, 2026
* feat: premium panel gating, code cleanup, and backend simplifications

Recovered stranded changes from fix/desktop-premium-error-unification.

Premium gating:
- Add premium field ('locked'|'enhanced') to PanelConfig and LayerDefinition
- Panel.showLocked() with lock icon, CTA button, and _locked guard
- PRO badge for enhanced panels when no WM API key
- Exponential backoff auto-retry on showError() (15s→30s→60s→180s cap)
- Gate oref-sirens and telegram-intel panels behind WM API key
- Lock gpsJamming and iranAttacks layer toggles, badge ciiChoropleth
- Add tauri-titlebar drag region for custom titlebar

Code cleanup:
- Extract inline CSS from AirlineIntelPanel, WorldClockPanel to panels.css
- Remove unused showGeoError() from CountryBriefPage
- Remove dead geocodeFailed/retryBtn/closeBtn locale keys (20 files)
- Clean up var names and inline styles across 6 components

Backend:
- Remove seed-meta throttle from redis.ts (unnecessary complexity)
- Risk scores: call handler functions directly instead of raw Redis reads
- Update OpenRouter model to gpt-oss-safeguard-20b:nitro
- Add direct UCDP API fetching with version probing

Config:
- Remove titleBarStyle: Overlay from tauri.conf.json
- Add build:pro and build-sidecar-handlers to build:desktop
- Remove DXB/RUH from default aviation watchlist
- Simplify reverse-geocode (remove AbortController wrapper)

* fix: cast handler requests to any for API tsconfig compat

* fix: revert stale changes that conflict with merged PRs

Reverts files to main versions where old branch changes would
overwrite intentional fixes from PRs #1134, #1138, #1144, #1154:

- news/_shared.ts: keep gemini-2.5-flash model (not stale gpt-oss)
- redis.ts: keep seed-meta throttle from PR #1138
- reverse-geocode.ts: keep AbortController timeout from PR #1134
- CountryBriefPage.ts: keep showGeoError() from PR #1134
- country-intel.ts: keep showGeoError usage from PR #1134
- get-risk-scores.ts: revert non-existent imports
- watchlist.ts: keep DXB/RUH airports from PR #1144
- locales: restore geocodeFailed/retryBtn/closeBtn keys

* fix: neutralize language, parallel override loading, fetch timeout

- Rename conflict zone from "War" to "Border Conflict", intensity high→medium
- Rewrite description to factual language (no "open war" claim)
- Load country boundary overrides in parallel with main GeoJSON
- Neutralize comments/docs: reference Natural Earth source, remove political terms
- Add 60s timeout to Natural Earth fetch script (~24MB download)
- Add trailing newline to GeoJSON override file

* fix: restore caller messages in Panel errors and vessel expansion in popups

- Move UCDP direct-fetch cooldown after successful fetch to avoid
  suppressing all data for 10 minutes on a single failure
- Use caller-provided messages in showError/showRetrying instead of
  discarding them; respect autoRetrySeconds parameter
- Restore cluster-toggle click handler and expandable vessel list
  in military cluster popups
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Country Brief] Modal can stay stuck on "Identifying…" / "Locating…" when reverse geocode fails or is aborted

2 participants