diff --git a/web/src/components/cards/cardRegistry.index.ts b/web/src/components/cards/cardRegistry.index.ts index 1a4b6cb767..7c02343a1b 100644 --- a/web/src/components/cards/cardRegistry.index.ts +++ b/web/src/components/cards/cardRegistry.index.ts @@ -1,4 +1,5 @@ import { isDynamicCardRegistered } from '../../lib/dynamic-cards/dynamicCardRegistry' +import { logger } from '../../lib/logger' import { registerAllDescriptorCards } from './cardDescriptors.registry' import { CARD_TITLES, CARD_DESCRIPTIONS, DEMO_EXEMPT_CARDS } from './cardMetadata' import { quantumCardRegistry } from './cardRegistry.quantum' @@ -83,7 +84,7 @@ registerAllDescriptorCards({ export function prefetchCardChunks(cardTypes: string[]): void { for (const type of cardTypes) { - CARD_CHUNK_PRELOADERS[type]?.()?.catch(() => {}) + CARD_CHUNK_PRELOADERS[type]?.()?.catch((e) => logger.warn('[CardRegistry] Failed to prefetch card chunk:', type, e)) } } @@ -123,7 +124,7 @@ export function prefetchDemoCardChunks(): void { () => import('./VClusterStatus'), ] - startupChunks.forEach(load => load().catch(() => {})) + startupChunks.forEach(load => load().catch((e) => logger.warn('[CardRegistry] Failed to prefetch demo card chunk:', e))) } const DEFAULT_CARD_WIDTH = 4 diff --git a/web/src/components/layout/SidebarCustomizer.tsx b/web/src/components/layout/SidebarCustomizer.tsx index 62f11ee903..d73fb58909 100644 --- a/web/src/components/layout/SidebarCustomizer.tsx +++ b/web/src/components/layout/SidebarCustomizer.tsx @@ -43,6 +43,7 @@ import { RouteSearchPanel } from './sidebar-customizer/RouteSearchPanel' import { renderIcon } from './sidebar-customizer/renderIcon' import { SidebarItemsPanel } from './sidebar-customizer/SidebarItemsPanel' import { SortableItem } from './sidebar-customizer/SortableItem' +import { logger } from '../../lib/logger' const createLocalDashboardId = () => `${LOCAL_DASHBOARD_ID_PREFIX}${crypto.randomUUID()}` @@ -204,7 +205,7 @@ export function SidebarCustomizer({ isOpen, onClose, embedded = false }: Sidebar ) if (item) updateItem(item.id, { icon: aiIcon }) }) - .catch(() => {}) + .catch((e) => logger.warn('[SidebarCustomizer] Failed to suggest dashboard icon:', e)) } const renderItemList = (items: SidebarItem[], target: 'primary' | 'secondary') => ( diff --git a/web/src/hooks/useStellarSource.ts b/web/src/hooks/useStellarSource.ts index 375b3f6341..c067ef14bd 100644 --- a/web/src/hooks/useStellarSource.ts +++ b/web/src/hooks/useStellarSource.ts @@ -1,4 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react' +import { logger } from '../lib/logger' import { getNextBatchTime, resolveStellarBatchIntervalMs } from '../components/stellar/lib/time' import { STORAGE_KEY_STELLAR_BATCH_INTERVAL_MS } from '../lib/constants/storage' import { areOptionalPollersSuppressed } from '../lib/constants/network' @@ -246,7 +247,7 @@ export function useStellarSource() { }) on<{ id: string; summary: string; suggest?: string }>('observation', payload => { setNudge({ id: payload.id, summary: payload.summary, suggest: payload.suggest, ts: new Date().toISOString() }) - stellarApi.getWatches().then(setWatches).catch(() => {}) + stellarApi.getWatches().then(setWatches).catch((e) => logger.warn('[StellarSource] Failed to refresh watches on observation:', e)) }) on<{ notifications?: StellarNotification[]; watches?: StellarWatch[]; pendingActions?: StellarAction[]; operationalState?: StellarOperationalState }>('initial_batch', batch => { if (batch.notifications) setNotifications(sortNotificationsByCreatedAt(batch.notifications)) @@ -256,7 +257,7 @@ export function useStellarSource() { }) on('watches', updated => setWatches(updated || [])) on('watch_update', updated => setWatches(prev => prev.map(watch => watch.id === updated.id ? updated : watch))) - es.addEventListener('watch_created', () => { stellarApi.getWatches().then(setWatches).catch(() => {}) }) + es.addEventListener('watch_created', () => { stellarApi.getWatches().then(setWatches).catch((e) => logger.warn('[StellarSource] Failed to refresh watches on watch_created:', e)) }) on('action_update', updated => { setPendingActions(prev => { const exists = prev.some(action => action.id === updated.id) @@ -273,7 +274,7 @@ export function useStellarSource() { ...prev, [payload.eventId]: { solveId: payload.solveId, eventId: payload.eventId, step: 'reading', message: 'Solve started — Stellar is on it.', actionsTaken: 0, status: 'running' }, })) - stellarApi.listSolves().then(setSolves).catch(() => {}) + stellarApi.listSolves().then(setSolves).catch((e) => logger.warn('[StellarSource] Failed to refresh solves on solve_started:', e)) }) on('solve_progress', payload => setSolveProgress(prev => ({ ...prev, [payload.eventId]: payload }))) on<{ solveId: string; eventId: string; status: string; summary: string }>('solve_complete', payload => { @@ -282,8 +283,8 @@ export function useStellarSource() { delete copy[payload.eventId] return copy }) - stellarApi.listSolves().then(setSolves).catch(() => {}) - stellarApi.listActivity(STELLAR_ACTIVITY_LIMIT).then(setActivity).catch(() => {}) + stellarApi.listSolves().then(setSolves).catch((e) => logger.warn('[StellarSource] Failed to refresh solves on solve_complete:', e)) + stellarApi.listActivity(STELLAR_ACTIVITY_LIMIT).then(setActivity).catch((e) => logger.warn('[StellarSource] Failed to refresh activity on solve_complete:', e)) }) on<{ id: string }>('action_bumped', payload => { setPendingActions(prev => { @@ -297,7 +298,7 @@ export function useStellarSource() { on('activity', entry => { setActivity(prev => (prev.some(item => item.id === entry.id) ? prev : [entry, ...prev].slice(0, STELLAR_ACTIVITY_LIMIT))) }) - es.addEventListener('digest_fired', () => { stellarApi.listSolves().then(setSolves).catch(() => {}) }) + es.addEventListener('digest_fired', () => { stellarApi.listSolves().then(setSolves).catch((e) => logger.warn('[StellarSource] Failed to refresh solves on digest_fired:', e)) }) on('catchup', payload => setCatchUp(payload)) on<{ content: string; period: string }>('digest', digest => { setNudge({ id: crypto.randomUUID(), summary: digest.content, ts: new Date().toISOString() }) diff --git a/web/src/lib/cache/cacheCore.ts b/web/src/lib/cache/cacheCore.ts index ad5dd0d8fe..c828e21b04 100644 --- a/web/src/lib/cache/cacheCore.ts +++ b/web/src/lib/cache/cacheCore.ts @@ -23,6 +23,7 @@ import { type Subscriber, workerRpc, } from './cacheStorage' +import { logger } from '../logger' import { isDemoMode, isEquivalentToInitial, @@ -139,7 +140,7 @@ export class CacheStore { try { await cacheStorage.set(this.key, data) if (workerRpc) { - _idbStorage.set(this.key, data).catch(() => {}) + _idbStorage.set(this.key, data).catch((e) => logger.warn(`[Cache] IDB worker write failed for ${this.key}:`, e)) } } catch (e: unknown) { console.error(`[Cache] Failed to save ${this.key}:`, e) @@ -593,7 +594,7 @@ export function useCache({ const dataAge = lastRefresh ? Date.now() - lastRefresh : Infinity const hasFreshData = !state.isLoading && !state.isRefreshing && dataAge < baseInterval if (!hasFreshData) { - refetch().catch(() => {}) + refetch().catch((e) => logger.warn(`[Cache] Initial refetch failed for ${key}:`, e)) } } @@ -602,7 +603,7 @@ export function useCache({ if (autoRefresh && !autoRefreshGloballyPaused && keepAliveActive) { if (!autoRefreshTimerRef.current) { autoRefreshTimerRef.current = setInterval(() => { - refetch().catch(() => {}) + refetch().catch((e) => logger.warn(`[Cache] Auto-refresh failed for ${key}:`, e)) }, effectiveInterval) } } else if (autoRefreshTimerRef.current) { @@ -619,9 +620,9 @@ export function useCache({ if (!autoRefreshTimerRef.current || !autoRefresh || autoRefreshGloballyPaused || !keepAliveActive) return clearInterval(autoRefreshTimerRef.current) autoRefreshTimerRef.current = setInterval(() => { - refetch().catch(() => {}) + refetch().catch((e) => logger.warn(`[Cache] Auto-refresh interval failed for ${key}:`, e)) }, effectiveInterval) - }, [effectiveInterval, autoRefresh, autoRefreshGloballyPaused, keepAliveActive, refetch]) + }, [effectiveInterval, autoRefresh, autoRefreshGloballyPaused, keepAliveActive, refetch, key]) useEffect(() => { return () => {