Skip to content

Fix/746 graceful offline handling - #748

Merged
evilguy4000 merged 3 commits into
DRYTRIX:mainfrom
Giorgio-Germani:fix/746-graceful-offline-handling
Sep 4, 2026
Merged

evilguy4000 merged 3 commits into
DRYTRIX:mainfrom
Giorgio-Germani:fix/746-graceful-offline-handling

Conversation

@Giorgio-Germani

Copy link
Copy Markdown

Description

This PR fixes the open issue #746 — "Service temporarily unavailable" error when the dashboard is left open: when the backend went down while a page stayed open (e.g. over lunch), the browser tab was left with a wall of SyntaxError: Failed to execute 'json'... "Offline" is not valid JSON messages, a loop of failing /api/chat/channels polls every 30 seconds, and stacked "Service temporarily unavailable" error cards whose Retry/Refresh buttons were unreachable.

Root cause: the service worker answers failing same-origin /api/* GETs with a synthetic plain-text Response('Offline', {status: 503}), which page code then tries to parse as JSON; each polling cycle produced a new identical error toast (max 4 kept), evicting the ones carrying recovery buttons; and the offline indicator bar was never removed on recovery.

Changes:

  • app/static/js/sw.js — synthetic offline API responses are now JSON ({"error":"Offline"}) with application/json, so .json() parsing no longer throws on top of the connectivity failure.
  • app/templates/components/persistent_chat_widget.html — channel/message loaders check response.ok before parsing; polling backs off to 2 minutes after a failure and skips while the tab is hidden.
  • app/static/error-handling-enhanced.js — repeated error-with-retry toasts are deduplicated (60 s window) so the toast with Retry/Refresh stays visible; the offline indicator is removed when connectivity is restored instead of lingering until a page reload.

The PR also carries two fixes ported from mobile-client-v2 that were never merged to main:

  • Idle needs-review flow — when a timer's idle grace expires with no window to answer, the entry is flagged needs review (web banner, service-worker push, scheduled-task detection, admin setting, v1 API endpoints, migration 183_add_idle_needs_review, desktop + browser-extension reporting).
  • Onboarding tour dismissibility — double-init guard, non-!important z-index layering, and a pending-skip guard so the "Are you sure you want to skip the tour?" confirmation stays readable and clickable.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality) — the idle needs-review flow
  • Breaking change (fix or feature that would change existing behavior)
  • Documentation update
  • Refactor (no functional change)

Checklist

  • My code follows the project's style guidelines (Black, flake8).
  • I have added/updated tests for my changes. (tests/test_api_v1.py extended for the needs-review endpoints)
  • All tests pass locally — pytest tests/test_api_v1.py: 40 passed; changed JS verified with node --check, Jinja templates parse-checked, JS bundles rebuilt.
  • I have updated the documentation if needed. (Unreleased entries added to CHANGELOG.md)
  • For user-facing changes, I have added an entry to the Unreleased section of CHANGELOG.md.

Related issues

Fixes #746


Deploy note: run flask db upgrade after merge (migration 183_add_idle_needs_review).

Giorgio added 3 commits September 3, 2026 15:15
Closes DRYTRIX#746. When the backend became unavailable while a page stayed
open, the service worker returned a plain-text 'Offline' response for
/api/* GETs, causing JSON parse errors, the chat widget polling loop
spammed failed requests every 30s, and identical error toasts stacked
up and evicted the ones carrying Retry/Refresh buttons.

- sw.js: synthetic offline API responses are now JSON
  ({"error": "Offline"}) with application/json content-type
- chat widget: check response.ok before parsing, back off polling to
  2 minutes after a failure, skip polls while the tab is hidden
- error handler: dedupe repeated error-with-retry toasts within the
  dedup window so the toast with Retry/Refresh buttons stays visible
- error handler: remove the offline indicator bar when connectivity
  is restored (previously it stayed until a full page reload)
…bile-client-v2

Cherry-pick of 0e85eae (web/backend/desktop/extension parts only —
mobile client excluded). When a timer's idle grace expires with the tab
closed, the entry is flagged for review; adds review banner, push/SW
handling, scheduled-task detection, migration 183, admin settings
toggle, and API/test coverage.

Also includes the onboarding skip-tour fix (double-init guard, z-index
layering for the skip confirmation, _skipPending tooltip guard).
@evilguy4000
evilguy4000 merged commit 958312b into DRYTRIX:main Sep 4, 2026
15 of 19 checks passed
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.

Error Service temporarily unavailable. Please try again in a few moments.

2 participants