Skip to content

fix(frontend): stop false Server Unreachable alerts while the tab is hidden#113

Merged
Valtora merged 1 commit into
mainfrom
fix/health-poll-hidden-tab-false-alarm
Jul 22, 2026
Merged

fix(frontend): stop false Server Unreachable alerts while the tab is hidden#113
Valtora merged 1 commit into
mainfrom
fix/health-poll-hidden-tab-false-alarm

Conversation

@Valtora

@Valtora Valtora commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Description

During a live meeting, the app raised two "Server Unreachable: Cannot connect to Nojoin Backend API." error toasts even though the backend was healthy the whole time and the recording completed with zero data loss.

Root cause is entirely client-side. The backend health poller in serviceStatusStore.ts runs on a setTimeout loop independent of tab visibility. When the Nojoin tab is backgrounded (as it is during a call the user is watching in another window), the browser throttles its timers and deprioritises its network requests, so the health probe's 5s AbortController times out even while the backend is fine. Three consecutive timeouts (backendFailCount > 2) trip the persistent "Server Unreachable" alert in ServiceStatusAlerts.tsx. Meanwhile the high-priority MediaRecorder segment uploads kept succeeding without a single sequence gap, so the poller was declaring the backend unreachable at the exact moments it was demonstrably reachable.

Log evidence from the incident: nojoin-api returned 200 across both windows, nojoin-nginx logged no errors/timeouts, segment sequences were gap-free for the affected recording, and the recording finalized 200 OK.

Fix: skip the probe (without accruing failures) when document.visibilityState === "hidden", guarded by typeof document !== "undefined" for SSR safety. The existing focus/visibilitychange handler in ServiceStatusAlerts.tsx already forces an immediate re-check on return to the foreground, so a genuine outage is still surfaced the moment the user looks at the tab.

No new dependencies.

Fixes # (n/a — reported from production logs)

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behaviour)
  • Documentation update

Checks run

  • Backend tests: source .venv/bin/activate && pytest (not run locally; frontend-only change, covered by CI "Backend tests")
  • Python quality: python scripts/check.py (not run; no Python touched)
  • Frontend lint: cd frontend && npm run lint
  • Frontend unit tests: cd frontend && npm run test (37 files, 182 tests passed)
  • Frontend build: cd frontend && npm run build
  • Docs validation: python3 scripts/validate_docs.py
  • Alembic validation: python3 scripts/validate_alembic.py

Migration impact

  • No database migration in this PR.

Documentation impact

  • No documentation change required.

Security impact

  • No security-sensitive change.

Manual verification

Added a unit test asserting checkBackend() does not fetch and does not increment backendFailCount while document.visibilityState is "hidden", and that previously-known-good status is preserved. Existing tests (which run under jsdom's default "visible" state) are unchanged and still pass.

Recommended manual smoke before merge: start a recording, switch to another window/tab for a couple of minutes so the Nojoin tab is backgrounded, confirm no "Server Unreachable" toast appears, return to the tab and confirm status stays healthy; separately, stop the backend while the tab is foregrounded and confirm the alert still fires as before.

@Valtora
Valtora merged commit 3619696 into main Jul 22, 2026
16 checks passed
@Valtora
Valtora deleted the fix/health-poll-hidden-tab-false-alarm branch July 22, 2026 14:38
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.

1 participant