From 83cba5a9efa040e1b7be994d8a4d204469bb3e1e Mon Sep 17 00:00:00 2001 From: jubnl Date: Tue, 5 May 2026 19:21:52 +0200 Subject: [PATCH] fix: handle QuotaExceededError in tripSyncManager with progressive eviction When IDB storage is full, syncTrip() throws an AbortError wrapping QuotaExceededError. Now: clear that trip's existing data and retry once; if quota is still exceeded, wipe all IDB data so the next sync starts fresh rather than silently failing on every subsequent call. --- client/src/sync/tripSyncManager.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/client/src/sync/tripSyncManager.ts b/client/src/sync/tripSyncManager.ts index 4129469b..865e9803 100644 --- a/client/src/sync/tripSyncManager.ts +++ b/client/src/sync/tripSyncManager.ts @@ -27,6 +27,7 @@ import { upsertCategories, upsertSyncMeta, clearTripData, + clearAll, } from '../db/offlineDb' import { prefetchTilesForTrip } from './tilePrefetcher' import { useSettingsStore } from '../store/settingsStore' @@ -69,6 +70,14 @@ function isPhoto(file: TripFile): boolean { return file.mime_type.startsWith('image/') } +function isQuotaError(err: unknown): boolean { + if (!(err instanceof Error)) return false + if (err.name === 'QuotaExceededError') return true + // Dexie wraps IDB errors: AbortError with inner QuotaExceededError + const inner = (err as { inner?: unknown }).inner + return inner instanceof Error && inner.name === 'QuotaExceededError' +} + // ── Core logic ──────────────────────────────────────────────────────────────── /** Fetch bundle + write all entities for one trip into Dexie. */ @@ -149,7 +158,22 @@ export const tripSyncManager = { try { await syncTrip(trip.id) } catch (err) { - console.error(`[tripSync] failed for trip ${trip.id}:`, err) + if (isQuotaError(err)) { + console.warn(`[tripSync] quota exceeded for trip ${trip.id}, clearing trip data and retrying`) + try { + await clearTripData(trip.id) + await syncTrip(trip.id) + } catch (retryErr) { + if (isQuotaError(retryErr)) { + console.warn('[tripSync] quota still exceeded after eviction — clearing all IDB data') + await clearAll() + return + } + console.error(`[tripSync] failed for trip ${trip.id} after eviction:`, retryErr) + } + } else { + console.error(`[tripSync] failed for trip ${trip.id}:`, err) + } } }