Skip to content
⚠️ This article was written in 2018. Some content may be outdated.

Frontend Error Monitoring: From window.onerror to Sentry

Production bugs are silent without monitoring — users just leave. Setting up error monitoring is one of the highest ROI investments for frontend projects.

Why You Need Error Monitoring ​

  • Browser environments vary wildly (OS, browser version, extensions, network)
  • You can't reproduce all user environments locally
  • Users rarely report bugs — they just stop using your app
  • Source maps let you see the actual code, not minified gibberish

window.onerror: The Foundation ​

javascript
window.onerror = function (message, source, lineno, colno, error) {
  // message: error message
  // source: script URL where error occurred
  // lineno, colno: line and column number
  // error: Error object (with .stack property)

  console.error("Uncaught error:", { message, source, lineno, colno });

  // Report to server
  fetch("/api/errors", {
    method: "POST",
    body: JSON.stringify({
      message,
      stack: error?.stack,
      url: window.location.href,
      userAgent: navigator.userAgent,
      timestamp: Date.now(),
    }),
  });

  return false; // don't suppress default browser error handling
};

Handling Unhandled Promise Rejections ​

window.onerror doesn't catch Promise rejections:

javascript
window.addEventListener("unhandledrejection", (event) => {
  const reason = event.reason;
  reportError({
    message: reason?.message || String(reason),
    stack: reason?.stack,
    type: "unhandledrejection",
  });
});

Cross-Origin Scripts ​

If your JS files are on a CDN (different origin), window.onerror receives "Script error." with no useful information due to browser security policies.

Fix: add crossorigin="anonymous" on the script tag AND set the appropriate CORS header on the CDN:

html
<script src="https://cdn.example.com/app.js" crossorigin="anonymous"></script>
// CDN response header
Access-Control-Allow-Origin: *

Source Maps ​

Minified code errors are useless. Source maps map minified positions back to original source:

javascript
// webpack.config.js
module.exports = {
  devtool: "hidden-source-map", // generate .map files, but don't link them in JS
};

Important: Don't expose source maps publicly (they reveal your source code). Upload them to your error reporting service, don't serve them to browsers.

Sentry Integration ​

Manual reporting gets complex fast. Sentry handles it all automatically:

bash
npm install @sentry/vue @sentry/tracing
javascript
// main.js
import * as Sentry from "@sentry/vue";
import { BrowserTracing } from "@sentry/tracing";

Sentry.init({
  app,
  dsn: "https://your-dsn@sentry.io/project-id",
  integrations: [
    new BrowserTracing({
      routingInstrumentation: Sentry.vueRouterInstrumentation(router),
    }),
  ],
  tracesSampleRate: 0.1, // 10% of transactions for performance monitoring
  environment: process.env.NODE_ENV,
  release: process.env.VUE_APP_VERSION,
});

Sentry automatically:

  • Captures uncaught errors and unhandled rejections
  • Links source maps for readable stack traces
  • Groups duplicate errors
  • Tracks affected users per error
  • Sends alerts on new issues

Report Errors Manually ​

javascript
// Capture a handled exception with context
try {
  const result = parseWeirdData(input);
} catch (err) {
  Sentry.captureException(err, {
    extra: { input, userId: currentUser.id },
    tags: { feature: "data-import" },
  });
}

// Add user context for all subsequent errors
Sentry.setUser({ id: user.id, email: user.email });

MIT Licensed