JavaScript Global Error Handling and Runtime Exceptions
The global error event acts as the final safety net in browser
environments, capturing unhandled runtime exceptions that bubble up from
different scripts, asynchronous callbacks, and dynamically loaded
modules. By listening to the global error event via
window.onerror or
window.addEventListener('error'), developers can log,
monitor, and gracefully handle uncaught errors throughout the entire
lifecycle of a web application without wrapping every execution block in
individual try...catch statements.
The Mechanism of Global Error Bubbling
When a JavaScript engine encounters an unhandled runtime error—such
as a TypeError or ReferenceError—the error
propagates up the call stack. If no active try...catch
block intercepts the exception, it reaches the global execution context
(window in browsers, or globalThis in modern
environments).
At this global boundary, the browser triggers the global
error event, passing critical metadata regarding the
failure to any registered global handlers.
Implementing Global Error Listeners
There are two primary methods to listen for global runtime errors:
1. window.onerror
The traditional approach assigns a callback function directly to
window.onerror. This callback receives five distinct
parameters:
window.onerror = function (message, source, lineno, colno, error) {
console.error("Caught globally:", {
message,
source,
lineno,
colno,
errorObject: error
});
// Returning true prevents the default browser error output in the console
return true;
};2.
window.addEventListener('error')
The modern approach uses the standard DOM Level 2 event listener
model, which receives a single ErrorEvent object containing
the error properties:
window.addEventListener('error', function (event) {
console.error("Runtime exception captured:", {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
error: event.error
});
});Capturing Across Different Script Types
The global error event operates across multiple script boundaries within the same document context:
- Inline and External Scripts: Errors occurring in
any
<script>tag on the page bubble to the same global handler. - Asynchronous Callbacks: Runtime exceptions inside
Web APIs like
setTimeout,setInterval,requestAnimationFrame, and DOM event listeners automatically bubble to the global scope when left unhandled. - Module Scripts: Errors thrown inside ES6 modules
(
<script type="module">) propagate to the global listener, provided they are not swallowed by asynchronous promise chains.
(Note: Unhandled promise rejections do not trigger the
error event directly; they require the
unhandledrejection event listener).
Handling Cross-Origin Script Restrictions
To prevent malicious cross-origin information leaks, browsers enforce
the Same-Origin Policy on error details. If a script hosted on an
external domain (such as a CDN) throws an exception, the global handler
will report a generic "Script error." with a line and
column number of 0, omitting the error object and stack
trace.
To allow the global error handler to capture full diagnostic details from external scripts, two requirements must be met:
- CORS Header on the Server: The server hosting the
script must include the
Access-Control-Allow-Origin: *(or your specific origin) HTTP response header. - The
crossoriginAttribute: The HTML<script>tag must declare thecrossoriginattribute:
<script src="https://cdn.example.com/app.js" crossorigin="anonymous"></script>Capturing Resource Loading Errors
The window.onerror handler only intercepts script
runtime exceptions. When static resources (such as
<img>, <link>, or
<script> tags) fail to load over the network, they
emit an error event targeted directly at the resource element.
These resource errors do not bubble up to window, but
they can still be captured globally by setting the
useCapture parameter to true on
addEventListener:
window.addEventListener('error', function (event) {
// Distinguish between resource loading errors and runtime exceptions
if (event.target && (event.target.src || event.target.href)) {
console.warn("Resource failed to load:", event.target);
}
}, true); // Event capturing phase enables interception