From b4900cb66fcb583c51dd33d199a2f2b925ddc22f Mon Sep 17 00:00:00 2001 From: Dorian Date: Thu, 12 Mar 2026 23:06:22 +0000 Subject: [PATCH] fix: replace all silent .catch(() => {}) with console.warn (BUG-F2) 13 silent catch handlers replaced with descriptive console.warn logging across 6 frontend files. No silent error swallowing remains. Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/FightViewer.vue | 4 ++-- frontend/src/composables/useNostr.ts | 6 +++--- frontend/src/game/audio/context.ts | 2 +- frontend/src/game/tts.ts | 6 +++--- frontend/src/pages/BotProfilePage.vue | 2 +- frontend/src/pages/FightPage.vue | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/FightViewer.vue b/frontend/src/components/FightViewer.vue index b781110..ad3fb32 100644 --- a/frontend/src/components/FightViewer.vue +++ b/frontend/src/components/FightViewer.vue @@ -468,7 +468,7 @@ async function _doReplay() { scene.startTalking('a') } // Ensure bubble stays visible for at least 400ms even if TTS resolves instantly - const minBubbleA = sleep(400).catch(() => {}) + const minBubbleA = sleep(400).catch(err => console.warn('[FightViewer] sleep interrupted:', err)) if (doTTS) { if (isCodeRound) await sfxModem() else await playAnswerNow(props.fight.botA!.name, round.botAResponse) @@ -495,7 +495,7 @@ async function _doReplay() { scene.showSpeechBubble('b', round.botBResponse, 8) scene.startTalking('b') } - const minBubbleB = sleep(400).catch(() => {}) + const minBubbleB = sleep(400).catch(err => console.warn('[FightViewer] sleep interrupted:', err)) if (doTTS) { if (isCodeRound) await sfxModem() else await playAnswerNow(props.fight.botB!.name, round.botBResponse) diff --git a/frontend/src/composables/useNostr.ts b/frontend/src/composables/useNostr.ts index cf0943e..167b77e 100644 --- a/frontend/src/composables/useNostr.ts +++ b/frontend/src/composables/useNostr.ts @@ -126,7 +126,7 @@ if (!autoRestoreRan && pubkey.value && !bot.value && getToken() && !isTokenExpir bot.value = normalizeBotData(data.bot) store('bf_bot', bot.value) } - }).catch(() => {}) + }).catch(err => console.warn('[Nostr] auto-restore failed:', err)) } else if (!autoRestoreRan && pubkey.value && !getToken()) { // No JWT — clear stale pubkey from before the JWT migration autoRestoreRan = true @@ -224,7 +224,7 @@ export function useNostr() { fetchNostrProfilePic(result.pubkey).then(pic => { profilePicUrl.value = pic store('bf_pic', pic) - }).catch(() => {}) + }).catch(err => console.warn('[Nostr] relay profile fetch failed:', err)) } else { freshlyGenerated = false profilePicUrl.value = null @@ -285,7 +285,7 @@ export function useNostr() { fetchNostrProfilePic(result.pubkey).then(pic => { profilePicUrl.value = pic store('bf_pic', pic) - }).catch(() => {}) + }).catch(err => console.warn('[Nostr] profile pic fetch failed:', err)) return result } finally { diff --git a/frontend/src/game/audio/context.ts b/frontend/src/game/audio/context.ts index 762b89a..5018cd1 100644 --- a/frontend/src/game/audio/context.ts +++ b/frontend/src/game/audio/context.ts @@ -29,7 +29,7 @@ export function initCtx() { export function getCtx(): AudioContext { if (!ctx) initCtx() if (ctx!.state === 'suspended') { - ctx!.resume().catch(() => {}) + ctx!.resume().catch(err => console.warn('[Audio] context resume failed:', err)) } return ctx! } diff --git a/frontend/src/game/tts.ts b/frontend/src/game/tts.ts index 4c2eafc..d8b3f6d 100644 --- a/frontend/src/game/tts.ts +++ b/frontend/src/game/tts.ts @@ -239,7 +239,7 @@ const _inflight = new Map>() function getAudioCtx(): AudioContext { if (!_audioCtx) _audioCtx = new AudioContext() - if (_audioCtx.state === 'suspended') _audioCtx.resume().catch(() => {}) + if (_audioCtx.state === 'suspended') _audioCtx.resume().catch(err => console.warn('[TTS] AudioContext resume failed:', err)) return _audioCtx } @@ -505,7 +505,7 @@ export function kokoroSpeak( if (staticUrl || _workerReady) { _generateAndCache(text, profileName).then(buf => { if (buf) _playBuffer(buf, dest, volume) - }).catch(() => {}) + }).catch(err => console.warn('[TTS] cache generation failed:', err)) return true } return false @@ -514,7 +514,7 @@ export function kokoroSpeak( /** Pre-generate audio in the worker so it's cached when needed. Fire-and-forget. */ export function kokoroPrefetch(text: string, profileName: string): void { if (!_workerReady) return - _generateAndCache(text, profileName).catch(() => {}) + _generateAndCache(text, profileName).catch(err => console.warn('[TTS] pre-cache generation failed:', err)) } /** Await until prefetched audio is cached and ready (max 2s). Returns true if cached, false on timeout/failure. */ diff --git a/frontend/src/pages/BotProfilePage.vue b/frontend/src/pages/BotProfilePage.vue index 4429a43..f8cd149 100644 --- a/frontend/src/pages/BotProfilePage.vue +++ b/frontend/src/pages/BotProfilePage.vue @@ -285,7 +285,7 @@ onMounted(async () => { if (stats.value?.ownerPubkey) { fetchNostrProfile(stats.value.ownerPubkey).then(p => { nostrProfile.value = p - }).catch(() => {}) + }).catch(err => console.warn('[BotProfile] webhook test failed:', err)) } // Poll queue for "choose your fight" diff --git a/frontend/src/pages/FightPage.vue b/frontend/src/pages/FightPage.vue index 7365a7b..1576fce 100644 --- a/frontend/src/pages/FightPage.vue +++ b/frontend/src/pages/FightPage.vue @@ -224,12 +224,12 @@ function wireSSE() { }, onRoundEnd(data) { if (_fightEnding) return // Don't start new round animations after fight is ending - _roundEndPromise = handleRoundEnd(data).catch(() => {}) + _roundEndPromise = handleRoundEnd(data).catch(err => console.warn('[FightPage] handleRoundEnd failed:', err)) }, onFightEnd(data) { if (_fightEnding) return // Deduplicate (only process first fight_end) _fightEnding = true - handleFightEnd(data).catch(() => {}) + handleFightEnd(data).catch(err => console.warn('[FightPage] handleFightEnd failed:', err)) }, }) } @@ -517,7 +517,7 @@ onMounted(async () => { // Cache finished fights for offline replay if (status === 'finished' && fight.value) { - cacheFight(fight.value).catch(() => {}) + cacheFight(fight.value).catch(err => console.warn('[FightPage] cacheFight failed:', err)) } isLoading.value = false