feat(frontend): integrate @sentry/sveltekit for browser and SSR error reporting to GlitchTip #591
Reference in New Issue
Block a user
Delete Branch "feat/issue-579-sentry-sveltekit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
@sentry/sveltekitnpm packagefrontend/src/hooks.client.tswithSentry.init()andhandleError = Sentry.handleErrorWithSentry()for browser-side error capturefrontend/src/hooks.server.tsto addSentry.init()andhandleError = Sentry.handleErrorWithSentry()for SSR error capture — existinghandlesequence (userGroup → handleAuth → handleLocaleDetection → handleParaglide) is preserved unchangedVITE_SENTRY_DSNwas already present in.env.example(added in the scaffold issue); when unset (the default),enabled: falseensures Sentry is fully inertChanged files
frontend/src/hooks.client.ts— new filefrontend/src/hooks.server.ts— Sentry init + handleError addedfrontend/package.json—@sentry/sveltekitdependency addedfrontend/package-lock.json— lockfile updatedTest plan
npm run check— no errors in hooks files (pre-existing type errors in other files are unrelated to this change)npm run build— production build succeeds (✔ done)VITE_SENTRY_DSNto a GlitchTip JavaScript project DSN and trigger a client-side error to confirm it appears in GlitchTipCloses #579
🤖 Generated with Claude Code
👨💼 Markus Keller — Senior Application Architect
Verdict: ✅ Approved
What I checked
Integration is at the correct layer — SvelteKit hooks are the right place for cross-cutting error capture. This doesn't cross any module boundary, doesn't touch domain logic, and doesn't add any new shared types. The
enabled: !!dsnguard is the correct pattern: zero runtime cost, zero network calls whenVITE_SENTRY_DSNis unset.No ADR required — this is an operational concern (observability wiring), not a structural decision.
Suggestions (non-blocking)
tracesSampleRate: 1.0means every request is traced. For a 5-user family archive this is harmless, but document it so a future contributor doesn't assume this was an oversight.Sentry.init()at the top ofhooks.server.tsbefore any imports from$lib/*is correct — Sentry must be initialized before the instrumented code runs.👨💻 Felix Brandt — Senior Fullstack Developer
Verdict: ⚠️ Approved with concerns
Blockers
Missing
sentrySvelteKit()Vite plugin — acceptance criterion "stack trace pointing to correct source file and line" will not be met in production buildsfrontend/vite.config.tsis unchanged. Without thesentrySvelteKit()Vite plugin, production bundles do not upload source maps to GlitchTip. Stack traces in captured events will show minified/transpiled code, not original TypeScript source file + line number.Issue AC explicitly states:
The fix is to add to
vite.config.ts:This also requires
SENTRY_AUTH_TOKENin.env/CI for source map upload at build time.Alternative resolution: relax the AC to "event appears in GlitchTip with a stack trace (source map upload is a follow-up)" and track that follow-up as a separate issue.
What's correct
handle = sequence(userGroup, handleAuth, handleLocaleDetection, handleParaglide)preserved unchanged ✓handleError = Sentry.handleErrorWithSentry()appended at the end ✓enabled: !!import.meta.env.VITE_SENTRY_DSN— clean gate, no SDK noise when DSN is absent ✓@sentry/sveltekitcorrectly placed independencies(notdevDependencies) — it's a runtime dependency ✓🔒 Nora Steiner (NullX) — Application Security Engineer
Verdict: ⚠️ Approved with concerns
No security regressions introduced. GlitchTip is self-hosted — error data stays within the family's own infrastructure, which eliminates the typical third-party data exfiltration concern with Sentry SDKs. The
enabled: falseguard is correctly implemented.Suggestions (low severity given self-hosted context)
1.
tracesSampleRate: 1.0— understand what's in those tracesAt 100%, every HTTP request generates a performance trace. The
@sentry/sveltekitSDK includes request URL, method, and status in transaction data. Verify that auth cookies and request bodies are not included in trace payloads by default (they aren't, per SDK defaults) — but worth confirming with a quick local test before relying on it in production.2. No
beforeSendhook — error events may contain personal dataException messages in a family archive context can contain document titles, person names, or path fragments. Since GlitchTip is self-hosted, this is low severity — but adding a
beforeSendgives future control over what's captured:3. Client-side DSN is public — expected, but document it (CWE-200, informational)
VITE_SENTRY_DSNis embedded in the browser bundle at build time — visible to anyone who inspects the JavaScript. This is by design (Sentry DSNs are intentionally public), but ensure GlitchTip's project settings have rate limiting enabled to prevent external actors from flooding your error queue with fake events.None of these are blockers given the self-hosted, family-only deployment context.
🧪 Sara Holt — QA Engineer
Verdict: ⚠️ Approved with concerns
The hooks integration is not unit-testable in the traditional sense (no inputs, no outputs to assert on), so I'm not flagging missing tests as a blocker. But there's one regression risk worth covering.
Suggestion
The "DSN absent → Sentry disabled" contract has no automated guard
The most likely future regression: someone removes the
enabledguard or changes the condition. This is verifiable with a Vitest unit test:This is a low-cost test that protects a meaningful behavior guarantee.
Note on pre-existing type errors
PR description mentions
npm run checkhas pre-existing errors unrelated to this change. These should have a tracking issue. They don't block this merge but represent accumulated technical debt in the type-checking layer.🖥️ Tobias Wendt — DevOps & Platform Engineer
Verdict: ✅ Approved
Clean infrastructure change. Checked:
@sentry/sveltekit: ^10.53.1independencies— runtime SDK correctly placed, not indevDependencies✓package-lock.jsoncommitted and updated — exact version is pinned in the lockfile even thoughpackage.jsonuses^. Reproducible builds maintained ✓VITE_SENTRY_DSN=already in.env.example(added in the scaffold issue) — no new env var needs to be documented in this PR ✓@babel/*packages losing"dev": truein the lockfile is expected:@sentry/sveltekitdepends on Babel at runtime (for instrumentation), which npm correctly promotes to a non-dev dependency. Not a concern ✓Nothing to flag on the ops/deployment side. The
VITE_prefix ensures the DSN ends up in the client bundle at build time, which is correct and expected for Sentry SDKs.📋 Elicit — Requirements Engineer
Verdict: ⚠️ Approved with concerns
Underspecification surfaced at review time
Acceptance criterion "stack trace pointing to correct source file and line" requires source map upload, which is not in scope of this PR.
The issue states:
This criterion requires:
sentrySvelteKit()Vite plugin +SENTRY_AUTH_TOKEN)None of steps 2–3 are implemented here. In development mode (
vite dev), inline source maps make this criterion passable. In a production build, the stack trace will show minified code.Recommendation: The original issue should have decomposed this into two acceptance criteria:
Suggest closing this issue as implemented (AC1 delivered) and opening a follow-up for source map upload configuration.
Verified Requirements
hooks.client.tshandleErrorevents captured viahooks.server.tshandlesequence (auth, locale, paraglide) preservedenabled: falsewhenVITE_SENTRY_DSNis unset — no network activity, no console errorsnpm run checkpasses,npm run buildsucceedspackage.jsonand lockfile updated🎨 Leonie Voss — UI/UX Designer & Accessibility Strategist
Verdict: ✅ Approved
This PR contains no user-facing changes. Checked:
handleErrorintegration ✓The
handleErrorWithSentry()wrapper passes errors through to SvelteKit's built-in error display (it wraps, not replaces, the error handler), so the user experience on error pages remains identical.LGTM from a UI/UX and accessibility perspective.
Felix's blocker resolved: added
sentrySvelteKit()Vite plugin tovite.config.ts.Source maps will be uploaded to GlitchTip at build time when
SENTRY_AUTH_TOKENis set.When the token is absent (dev, CI), upload is disabled via
autoUploadSourceMaps: false— the build succeeds normally.SENTRY_AUTH_TOKEN=added to.env.example.