Error Monitoring
An error-reporting service — Sentry, Bugsnag, Rollbar or similar — capturing unhandled client exceptions and server errors with stack traces, source maps, release tagging, grouping, and alerting. No such SDK is installed anywhere in the repo, and there is no OpenTelemetry instrumentation.
This is the app-level counterpart to a decision already recorded on the infrastructure side: Observability explains why Application Insights and Log Analytics are deliberately not provisioned. That page owns the cost argument for platform telemetry; this one is about application exceptions, which a separate product would capture and which that decision does not by itself settle.
What exists instead
Errors are surfaced, just never collected:
app/plugins/errorHandler.tshooks Nuxt'svue:errorand writes the error to the console with itsinfostring. Every error, with nothing filtered — an offline failure prints like any other, because a console that silently drops one class of error can no longer be read as evidence that nothing failed. That is the whole global client handler — nothing is transmitted anywhere.app/plugins/warnHandler.tswraps Vue'swarnHandlerto suppress one known-benign slot warning, so real warnings stay visible in development.- The tRPC link stack in
app/plugins/trpc.tssplits the two jobs a failed call has.loggerLinkis configured to stay quiet in production except for down-direction results that areErrorinstances, so a failing procedure still prints.errorLinkis the user-facing half — it raises the alert the person actually sees, and an offline failure carries nodatashape, so it never reaches the alert.loggerLinkis what still prints it:errorLinkforwards the failure throughobserver.error(err), which a caller may catch, so the console entry comes from the log link rather than from an unhandled rejection. - Server-side, failures reach the console through the neverthrow convention — a chain that can fail terminates in
.orTee(console.error)rather than swallowing. Those writes land in the host's log stream and nowhere durable. app/error.vueis the boundary itself. Nuxt renders it in place ofapp.vue, so it carries its own Vuetify shell rather than inheriting the app's, and it turns an escaped error into a page that says which of the two things happened — a route that does not exist, or a failure — and offers the way back that fits. It reports nothing anywhere either; it is the surface, not the collection.
Why deferred
- A tracker's value is alerting and triage across a stream of reports from users you cannot ask. With a single operator and a small user base, the console in front of you and a reproduction attempt answer the same question at zero cost — the same "no consumer for the telemetry" argument the infra decision makes, applied one layer up.
- Error payloads carry user content: message bodies in a tRPC input, resource names, file names. Shipping them to a third party makes that vendor a data processor for the platform's private rooms — a real commitment, not a config line, and one that should be made deliberately rather than as a best-practice reflex.
- Free tiers exist, but the ongoing cost is not the invoice; it is that an unwatched tracker fills with unactioned reports and trains everyone to ignore it.
Revisit when
A user reports a bug that cannot be reproduced from the console — meaning the failure only exists in someone else's browser or session — or the platform gains enough real users that failures happen while nobody is looking at a log stream.
Cheaper interim
The one gap worth closing without a service was the boundary page, and it is closed — an escaped error now lands on ours rather than the framework's. Everything else stays as it is: the console handler, the loggerLink production filter, and .orTee(console.error) on the server. None of them transmits anything, which is the whole of what adopting a tracker would change.
