The gap nobody notices
You have logs. An exception is in them. And nobody reads logs when nothing appears to be wrong, which is exactly the situation where a bug affecting 2% of users lives for four months.
The fix is a piece of infrastructure that is small: catch unhandled exceptions, send them somewhere, and have that somewhere group identical errors together and count them.
What an error tracker does that a log file cannot
- Grouping. Ten thousand occurrences of the same exception become one item with a count, instead of ten thousand lines.
- First seen and last seen. The two most useful timestamps in an incident.
- Release tagging. Tie every event to the deployed commit and the question “did we cause this?” is answered by looking at when it started.
- Breadcrumbs. The sequence of events before the exception: the route, the query, the user action.
- Stack traces that survive minification. For browser JavaScript, this is the whole game. Without uploaded source maps, your stack trace reads
a.b.c:1:4213and is worth nothing. With them, it points at a line of your code.
Wiring it up is twenty minutes
Three things to add on the server:
process.on("uncaughtException", (err) => { report(err); process.exit(1); });
process.on("unhandledRejection", (err) => { report(err); });Both matter. A Node process that swallows an uncaughtException keeps running in an unknown state, which is worse than crashing: a supervisor restarts a crashed process in a second; nothing restarts a wedged one.
Then a middleware that reports any error escaping a route handler, and a client-side handler for browser errors.
The noise, and why people stop looking
Turn on browser error reporting and your feed fills with things you cannot fix:
- Browser extensions injecting scripts and throwing inside them.
ResizeObserver loop completed with undelivered notifications: benign, extremely common.- Network errors from users on trains, in lifts, and on hotel wifi.
- Bots probing for
/wp-adminand generating 404 handlers. - A cross-origin script error reported as the useless string
Script error.
If you do not filter these, the feed becomes wallpaper within a week and you stop opening it, which returns you to where you started. So: ignore-list the known noise, sample high-volume non-actionable errors, and be willing to mark things as ignored. A feed with six items you believe is worth more than one with six hundred you do not.
What not to send
Error payloads are a privacy leak waiting to happen. Sending the whole request object attaches the Authorization header, session cookies, the password from the login form and whatever the user typed.
Scrub at the client, before sending: drop headers by name, drop known sensitive fields, truncate bodies. Every SDK has a hook for this; use it before you turn the SDK on rather than after.
Errors are not alerts
An error tracker is a queue of things to look at, not a pager. The rule of thumb:
- A new error type appearing after a deploy: worth a notification.
- An error rate crossing a threshold: worth an alert, but that belongs with your metrics.
- The 400th occurrence of a known issue: worth nothing at all; you already know.
Wiring every error to a notification channel produces exactly the fatigue the next lesson is about.
The free path
Sentry has a free tier of a few thousand events a month, which is more than a small site produces, and its SDKs are the best in this space. GlitchTip is open source, self-hostable, and speaks the Sentry protocol, so the same SDKs work against it. Bugsnag and Rollbar are the paid alternatives.
And if you want none of them: a fifty-line handler that POSTs a JSON payload to a webhook and appends it to a table gets you grouping by a hash of the stack trace and a count. That is 80% of the value. The point is not the tool. The point is that a human learns about the exception without going looking.
Every lesson here is open. Your progress is recorded once you pass the Agents and Automation exam.
Check your understanding
You add browser error reporting and within a week the feed has 600 items a day, mostly from extensions, cross-origin Script error. entries and network failures on mobile. Your team has stopped opening it. What is the correct response?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Tri, your AI tutor
