Page MenuHomePhabricator

Uncaught errors: inform the editor, or log, or both
Open, Needs TriagePublic

Description

At the moment, uncaught errors are silently ignored in production. This means anything from small UI errors to serious data corruption can happen unbeknownst to both the editor and the developers. To improve this, we should consider installing a default handler to be called for any uncaught error (using window.onerror). This handler could:

  • notify the user, or
  • send info to be logged temporarily on the server side, or
  • both.

Any logging would likely have to be non-public and temporary, because the nature of a default uncaught error handler makes it hard to ascertain what information the error might contain. The mechanisms to set a handler are page-global, so we must consider how we interact with non-VisualEditor code.

Technical details

(See window.onerror documentation for a general intro: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror )

There are three types of situation where code in VE is likely to give rise to unhandled errors:

// Type 1: Uncaught error thrown synchronously
throw new Error( 'foo' );

// Type 2: Uncaught error thrown in a setTimeout
setTimeout( function () {
    throw new Error( 'bar' );
} );

// Type 3: Uncaught error thrown in a promise handler
$.when( true ).then( function () {
    throw new Error( 'baz' );
} );

Type 1: an uncaught error thrown synchronously is passed automatically to window.onerror. Five parameters are passed:

window.onerror = function ( message, sourceFile, lineNo, colNo, errorObject ) {
    // ...
};

The error object contains the stack trace.

Type 2: An uncaught error thrown in a setTimeout is also passed automatically to window.onerror. However the stack trace only contains the most recent synchronous part, i.e. not stepping back out through the setTimeout.

Type3: An uncaught error thrown in a promise handler is *not* passed to window.onerror . For jQuery promises we have jQuery.Deferred.exceptionHook (see T168086). For native promises there is window.onunhandledrejection.

These are page-global handlers so we have to consider how they interact with non-VisualEditor code on the page. We have the stack traces so it's probably possible to use that to detect whether an error has been thrown inside VE code (or indeed "through" VE code).