Repository navigation
fix(web): route handled errors to Sentry, enforce no-console - #1296
Conversation
19 catch blocks across 9 components logged errors with bare console.error, invisible to Sentry (the logging-hardening ADR Track B sweep that never happened). Adds reportError(message, error, context) to lib/sentry.ts — captureFrontendException + console echo so dev visibility survives without a DSN — and replaces every bare call site with component/action context. Enforcement: frontend eslint no-console (allow warn), with overrides for Node build scripts (console is their interface) and the two sanctioned echoes (reportError itself, ErrorBoundary's errorInfo dump which already captures). Verified: lint --max-warnings 0 clean, 733/733 vitest pass, tsc clean. Closes #1278
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
Warning Review limit reached
More reviews will be available in 10 minutes and 3 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (12)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Failed to generate code suggestions for PR |
|
|
Size Change: +353 B (+0.08%) Total Size: 434 kB 📦 View Changed
ℹ️ View Unchanged
|
) ## What First concrete delta for **#1286 Track B3** (silent-catch sweep on external/IO call paths): `FeatureToggleService.getDbGlobalOverride` no longer swallows DB errors to `null` without a trace. ```ts } catch (error) { warnLog({ message: 'Failed to read global feature toggle override; falling back to config default', error, data: { name }, }) return null } ``` ## Why The previous `catch { return null }` made a **DB outage indistinguishable from "no override set"** — the caller (`getGlobalToggleStatus`) treats `null` as "fall back to the env/config default", so a persistent database failure silently degraded every global feature toggle to its config value with zero observability. The fail-open-to-config behavior is **correct and intentionally preserved** — this only adds a `warnLog` so the failure is visible. `warn` (not `error`) because the path is gracefully handled. ## Scope note This PR is the *only* genuine finding from a read-only sweep of the four external-API families called out in #1286's next-increment (Spotify, Last.fm, Discord, Prisma). The rest of those paths already log via `errorLog` / `warnLog` / `logAndSwallow` / `logAndWarn` before any swallow — the codebase's existing discipline (#1296/#1302/#1352/#1358) already covers them. The broader "promote empty-catch lint warn→error" item (~2026-06-26) and the Track C requestId issue remain as tracked in #1286. ## Verification - `tsc --noEmit` clean; shared build clean. - Extended the existing `FeatureToggleService.spec.ts` "db throws" test to assert the warning is emitted (`warnLog` called once with the error + `{ name }`). - Shared suite green: **829/829** (61 suites). Refs #1286. @cubic-dev-ai please review. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Log database errors when reading global feature toggle overrides so outages are visible while still falling back to config defaults. Addresses #1286 (Track B3) by surfacing failures on an external/IO path. - **Bug Fixes** - `FeatureToggleService.getDbGlobalOverride` now calls `warnLog({ message, error, data: { name } })` on DB errors, then returns `null`. - Extended unit test to assert the warning is emitted when the DB read throws. <sup>Written for commit 3ffc0b4. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1411?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
🤖 I have created a release *beep* *boop* --- <details><summary>2.18.0</summary> ## [2.18.0](v2.17.0...v2.18.0) (2026-06-19) ### Features * **autoplay:** add implicit-dislike-penalty signal ([#1374](#1374)) ([593c0ad](593c0ad)) * **autoplay:** add recency-decay signal for queue diversity ([#1376](#1376)) ([b85e2a0](b85e2a0)) * **autoplay:** boost candidates for frequently replayed tracks ([#1370](#1370)) ([215edea](215edea)) * **autoplay:** guild opt-out toggle for sertanejo veto ([#1087](#1087)) ([#1373](#1373)) ([6cb5588](6cb5588)) * **autoplay:** instrument outcome eval to disambiguate [#1275](#1275) ([#1491](#1491)) ([1921ab5](1921ab5)) * **backend:** add zod validation to artists and toggles routes ([#1189](#1189)) ([#1334](#1334)) ([b59fb35](b59fb35)) * **backend:** dedup key for support-report intake ([#1319](#1319)) ([#1328](#1328)) ([4d95307](4d95307)) * **backend:** move session store from Redis to Postgres ([#1111](#1111)) ([#1396](#1396)) ([ff5e0b6](ff5e0b6)) * **backend:** request-id correlation middleware for [#1286](#1286) ([#1417](#1417)) ([671ed4c](671ed4c)) * **bot:** instrument serversetup criativaria invocations ([#1288](#1288)) ([#1390](#1390)) ([c37f021](c37f021)) * **bot:** utility join-onboarding message + in-bot growth adr ([#1506](#1506)) ([0a23775](0a23775)) * **db:** add check constraints on guild_settings bounds ([#1124](#1124)) ([#1338](#1338)) ([a7c7400](a7c7400)) * growth surfaces — /invite, landing SEO + CTA, guild telemetry ([#1494](#1494)) ([205876d](205876d)) * **music:** add previous-track command end to end ([#1239](#1239)) ([#1347](#1347)) ([7771167](7771167)) * **observability:** alert on redis control publish failures ([#1401](#1401)) ([6e46cd7](6e46cd7)) * **security:** add security headers + csp report-only ([#1283](#1283)) ([#1315](#1315)) ([7413a1c](7413a1c)) * **security:** collect CSP violations via report-uri sink ([#1283](#1283)) ([#1415](#1415)) ([6f68aa3](6f68aa3)) * skip-reason telemetry via emoji reactions on now-playing ([#1377](#1377)) ([5b1959f](5b1959f)) ### Bug Fixes * add timeouts to unbounded external fetch calls ([#1333](#1333)) ([38dde55](38dde55)) * **auth:** log session lookup failures in optional auth ([#1286](#1286)) ([ff2b3ab](ff2b3ab)) * **autoplay:** capture skip rejections (symmetric completion threshold) ([#1276](#1276)) ([c282414](c282414)) * **autoplay:** key track start-time per track, not per guild ([#1275](#1275)) ([#1483](#1483)) ([0853a90](0853a90)) * **autoplay:** provenance-aware genre guards open the seed neighborhood ([#1272](#1272)) ([405af1e](405af1e)) * **autoplay:** weight popularity over name similarity in similar mode ([#1273](#1273)) ([cb24a7e](cb24a7e)) * **backend:** bound pagination limit on leaderboard + starboard entries ([#1307](#1307)) ([c2b5cbe](c2b5cbe)) * **backend:** degrade gracefully on external fetch timeouts ([#1342](#1342)) ([#1345](#1345)) ([5de7b69](5de7b69)) * **backend:** log swallowed spotify search errors ([#1285](#1285)) ([#1318](#1318)) ([72a7431](72a7431)) * **backend:** replayed named creates return existing row ([#1320](#1320)) ([#1326](#1326)) ([be2b30c](be2b30c)) * **backend:** validate guildId snowflake on all 18 music routes ([#1297](#1297)) ([b93cfb5](b93cfb5)) * **bot:** accurate reply when previous button has no history ([#1191](#1191)) ([#1331](#1331)) ([eb9b2ea](eb9b2ea)) * **bot:** bound all Spotify API fetches with an 8s abort deadline ([#1302](#1302)) ([b283159](b283159)) * **bot:** catch resume errors in skip delayed play ([#1353](#1353)) ([#1354](#1354)) ([c2d2758](c2d2758)) * **bot:** catch settings fetch errors in idle disconnect scheduling ([#1361](#1361)) ([61b82e4](61b82e4)) * **bot:** extend graceful bot-perm guard to mgmt + automod ([#1502](#1502)) ([1ee510d](1ee510d)) * **bot:** graceful bot-permission guard + moderation pilot ([#1498](#1498)) ([#1499](#1499)) ([e2664ce](e2664ce)) * **bot:** harden youtube extractor registration ([#1468](#1468)) ([#1472](#1472)) ([2e7f1bb](2e7f1bb)) * **bot:** queue summary position is milliseconds, not seconds ([#1202](#1202)) ([#1330](#1330)) ([efa9800](efa9800)) * **bot:** skip startup session restore into empty voice channel ([#1469](#1469)) ([dbcc08c](dbcc08c)) * **bot:** thread real Client into endGiveaway ([#1383](#1383)) ([#1388](#1388)) ([d3b274a](d3b274a)) * **bot:** wire setupwebmusichandler at startup ([#1321](#1321)) ([#1351](#1351)) ([dc68e7e](dc68e7e)) * **ci:** grant review-tools caller the scopes its reusables require ([#1424](#1424)) ([c215675](c215675)) * **ci:** quality/Lint green again — core rules off for bot/shared at root lint ([#1364](#1364)) ([#1365](#1365)) ([cc2322f](cc2322f)) * **compose:** tag container logs so loki labels them by name ([#1476](#1476)) ([4e956df](4e956df)) * **deps:** bump multer to 2.2.0 to fix high-severity dos advisory ([#1493](#1493)) ([4d57ac8](4d57ac8)) * **deps:** bump qs to 6.15.2 and hono to 4.12.25 (audit) ([#1295](#1295)) ([ae5d949](ae5d949)) * **deps:** pin piscina 4.9.3 for high-severity rce advisory ([#1504](#1504)) ([10b68e6](10b68e6)) * **docker:** add C toolchain to deps-production for opus source-build fallback ([#1310](#1310)) ([5ed7f11](5ed7f11)) * **download:** drop invalid --extract-flat flag from yt-dlp download ([#1488](#1488)) ([9d29144](9d29144)) * **frontend:** default add-to-discord cta to public application id ([#1495](#1495)) ([efda71e](efda71e)) * **help:** split large command categories across embed fields ([#1489](#1489)) ([0fa5786](0fa5786)) * **player:** warn not error on bridge exhaustion for unplayable tracks ([#1507](#1507)) ([d7a4a58](d7a4a58)) * **security:** bump vite 8.0.16 + form-data 4.0.6 for high advisories ([#1457](#1457)) ([58d21d5](58d21d5)) * **shared:** env-isolate environment.test.ts (no secret dumps) ([#1292](#1292)) ([588037c](588037c)) * **shared:** log db error in feature-toggle override read ([#1286](#1286)) ([#1411](#1411)) ([0dfc409](0dfc409)) * **shared:** make read-then-write service paths atomic ([#1199](#1199)) ([#1340](#1340)) ([ba1b840](ba1b840)) * **shared:** normalize embed template name on gettemplate ([#1327](#1327)) ([#1350](#1350)) ([d221b57](d221b57)) * **shared:** safe env parsing via parseIntEnv helper ([#1209](#1209)) ([#1335](#1335)) ([32e3684](32e3684)) * **shared:** validate guildautomation json on read ([#1194](#1194)) ([#1346](#1346)) ([93d9eea](93d9eea)) * **spotify:** log oauth token-exchange failures ([#1286](#1286) track b) ([8306c35](8306c35)) * **twitch:** re-subscribe to EventSub after unexpected reconnect ([#870](#870)) ([#1395](#1395)) ([78a30f3](78a30f3)) * **twitch:** refresh bot subscriptions on web add/remove ([#870](#870)) ([939d4b3](939d4b3)) * **web:** clear auth check promise on settle, not via 100ms timer ([#1311](#1311)) ([5cc8eef](5cc8eef)) * **web:** report swallowed member-context fetch error to Sentry ([#1286](#1286) B3) ([#1416](#1416)) ([85f141d](85f141d)) * **web:** route handled errors to Sentry, enforce no-console ([#1296](#1296)) ([a34e777](a34e777)) ### Performance Improvements * **bot:** bound external scrobbler track cache with lru+ttl ([#1282](#1282)) ([#1316](#1316)) ([7f29efc](7f29efc)) * **shared:** batch recommendation telemetry counts in one groupBy ([#1308](#1308)) ([e5a5973](e5a5973)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Release 2.18.0 with smarter autoplay, a previous-track command, stronger security/telemetry, and Postgres-backed sessions. This improves stability across the bot, backend, and web apps. - **New Features** - Smarter autoplay with new ranking signals (implicit dislike, recency decay, replay boost), a guild opt-out, and outcome/skip telemetry. - Previous-track command end to end. - Security headers and CSP report-only with violation collection. - Session store moved from Redis to Postgres plus request-id correlation middleware. - **Bug Fixes** - Add timeouts and graceful fallbacks for external calls; bound pagination limits and validate guild IDs. - Harden bot behavior: permission guards, YouTube extractor registration, correct queue position and previous-button messaging, skip session restore into empty channels. - Improve observability: route handled errors to Sentry, surface swallowed errors, alert on Redis publish failures. - Security updates to dependencies (`multer`, `qs`, `hono`, `vite`, `form-data`) and pin `piscina`; add a C toolchain in Docker for opus fallback. <sup>Written for commit d28bef3. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1508?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->



What
Closes #1278 — the frontend monitoring blind spot from the test-sweep/backlog audit, and the Track B remnant of ADR 2026-06-01-logging-observability-hardening.
Changes
lib/sentry.ts: newreportError(message, error, context)— forwards tocaptureFrontendExceptionand echoes to the console so local dev (no DSN) keeps visibility.console.errortoreportErrorwith{ component, action }context — bare sites gained descriptive messages derived from their enclosing handlers.no-console: ['error', { allow: ['warn'] }]so new bareconsole.errorcan't land. Overrides:scripts/**(Node CLI tooling — console is the interface), plus the two sanctioned echoes (insidereportErroritself; ErrorBoundary'serrorInfodump, which already captures separately).Verification
eslint --max-warnings 0clean (rule live, zero violations)tsc --noEmitclean across all workspaces (pre-commit hook)Summary by cubic
Routes handled frontend errors to Sentry and blocks bare
console.errorusage to fix the monitoring blind spot. Improves production visibility and closes #1278.reportError(message, error, context)in@/lib/sentryto capture to Sentry and echo to console for dev without a DSN.console.errorcalls across 9 components withreportErrorincluding{ component, action }context.no-console: ['error', { allow: ['warn'] }]in the frontendeslintconfig; override forscripts/**; allowed console echo insidereportErrorandErrorBoundaryonly.Written for commit 7b2a9f4. Summary will update on new commits.