Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiled Minified JS is not exposing a usable Stack Trace on Error #25235

Closed
raphaeladam-wf opened this issue Dec 11, 2015 · 15 comments

Comments

@raphaeladam-wf
Copy link

commented Dec 11, 2015

I'm no longer able to capture usable Stack Traces from errors in a minified dart2js app with the 1.13.0 SDK. This is problematic because we capture the minified Stack Trace in the JS app to run it through the source_map_stack_trace package.

void main() {
  ...
  window.onError.listen((ErrorEvent e) {
    log.severe(e.message);
    ...
  }
}

SDK 1.12.1:

bootstrap.dart.js:1779 Uncaught Uncaught Error: Bad state: Unable to fetch Vessel session: XMLHttpRequest error.
Stack Trace:
Bad state: Unable to fetch Vessel session: XMLHttpRequest error.
    at dart.j (http://localhost:1040/bootstrap.dart.js:1779:3)
    at Jm.dart.Jm.$1 (http://localhost:1040/bootstrap.dart.js:27008:14)
    at dart.EL (http://localhost:1040/bootstrap.dart.js:12007:24)
    at a5J.dart.a5J.f9 (http://localhost:1040/bootstrap.dart.js:13922:16)
    at a6N.dart.a6N.$0 (http://localhost:1040/bootstrap.dart.js:12570:12)
    at dart.a7.static.hp (http://localhost:1040/bootstrap.dart.js:12495:75)
    at a7.cl (http://localhost:1040/bootstrap.dart.js:12442:3)
    at a6H.dart.a6H.$0 (http://localhost:1040/bootstrap.dart.js:12537:23)
    at dart.EJ (http://localhost:1040/bootstrap.dart.js:12004:9)
    at a5J.dart.a5J.ct (http://localhost:1040/bootstrap.dart.js:13918:16)

SDK 1.13.0:

Uncaught NullError: method not found: 'bl' on null

SDK Info: Dart VM version: 1.13.0 (Wed Nov 18 12:15:29 2015) on "macos_x64"

@travissanderson-wf

This comment has been minimized.

Copy link

commented Dec 22, 2015

is there any update on this? it makes tracking down production issues near impossible on the 1.13.0 SDK

@kevmoo

This comment has been minimized.

Copy link
Member

commented Dec 22, 2015

@travissanderson-wf @raphaeladam-wf Is it easy to reproduce? Could you try with the latest 1.14-dev release and see if it's still there?

@sigmundch

This comment has been minimized.

Copy link
Member

commented Dec 22, 2015

mmm - I'm not yet able to reproduce the problem - in part e.message is only giving me the error message both in 1.12.1 and in 1.13.0. Are there more details on how you are extracting the stack trace from the error that are not shown above?

Here is what I'm doing:

main() {
  window.onError.listen((e) => print(e.message));
  document.body.onClick.listen((e) => foo());
}

foo() {
  ...
  // foo internally throws, but I made the code deep
  // enough to have some interesting stack trace
}

Another question: are you also seeing this issue when you use try-catch blocks? or only for asynchronous errors on window.onError? 1.13.0 didn't have that many changes on this. The main related change I recall was this commit (5363e5c) that was meant to improve how we capture the stack trace for errors thrown on async callbacks. Seems to be closely related to this, so it's possible that the bug was introduced there.

@raphaeladam-wf

This comment has been minimized.

Copy link
Author

commented Dec 22, 2015

I have an example app here:
broken_app.zip

Built with 1.13.0 SDK

index.bootstrap.initialize.dart.js:4403 ErrorEvent: Instance of 'cd'
2015-12-22 13:52:45.575 index.bootstrap.initialize.dart.js:4403 ErrorEvent.error: NoSuchMethodError: method not found: 'ee' (C.f.ee is not a function)
2015-12-22 13:52:45.575 index.bootstrap.initialize.dart.js:4403 ErrorEvent.fileName: http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js
2015-12-22 13:52:45.575 index.bootstrap.initialize.dart.js:4403 ErrorEvent.message: Uncaught NoSuchMethodError: method not found: 'ee' (C.f.ee is not a function)
2015-12-22 13:52:45.575 index.bootstrap.initialize.dart.js:4403 ErrorEvent.type: error

Built with 1.12.1 SDK

index.bootstrap.initialize.dart.js:4446 ErrorEvent: Instance of 'ErrorEvent'
2015-12-22 14:48:24.966 index.bootstrap.initialize.dart.js:4446 ErrorEvent.error: Uncaught Error: NoSuchMethodError: method not found: 'ej' (C.f.ej is not a function)
Stack Trace:
TypeError: C.f.ej is not a function
    at bI.dart.bI.eM (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5410:29)
    at eval (eval at <anonymous> (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1270:8), <anonymous>:2:34)
    at dart.eh (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1083:69)
    at eY.dart.eY.b4 (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5176:10)
    at eY.dart.eY.aA (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5177:30)
    at kR.dart.kR.$2 (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4827:20)
    at dart.eh (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1083:112)
    at dart.kg (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4125:14)
    at http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4242:63
    at main-app.reverseText (http://localhost:63342/untitled4/build/web/index.html:10902:21)
2015-12-22 14:48:24.966 index.bootstrap.initialize.dart.js:4446 ErrorEvent.fileName: http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js
2015-12-22 14:48:24.966 index.bootstrap.initialize.dart.js:4446 ErrorEvent.message: Uncaught Uncaught Error: NoSuchMethodError: method not found: 'ej' (C.f.ej is not a function)
Stack Trace:
TypeError: C.f.ej is not a function
    at bI.dart.bI.eM (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5410:29)
    at eval (eval at <anonymous> (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1270:8), <anonymous>:2:34)
    at dart.eh (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1083:69)
    at eY.dart.eY.b4 (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5176:10)
    at eY.dart.eY.aA (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:5177:30)
    at kR.dart.kR.$2 (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4827:20)
    at dart.eh (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:1083:112)
    at dart.kg (http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4125:14)
    at http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js:4242:63
    at main-app.reverseText (http://localhost:63342/untitled4/build/web/index.html:10902:21)
2015-12-22 14:48:24.966 index.bootstrap.initialize.dart.js:4446 ErrorEvent.type: error
@raphaeladam-wf

This comment has been minimized.

Copy link
Author

commented Dec 22, 2015

@kevmoo I'll give 1.14 a whirl

@raphaeladam-wf

This comment has been minimized.

Copy link
Author

commented Dec 22, 2015

@kevmoo Upgrading to 1.14.0 does not appear to resolve the issue

Built with 1.14.0-dev.1.0 SDK:

ErrorEvent: Instance of 'ce'
2015-12-22 15:19:35.932 index.bootstrap.initialize.dart.js:4386 ErrorEvent.error: NoSuchMethodError: method not found: 'e9' (C.f.e9 is not a function)
2015-12-22 15:19:35.932 index.bootstrap.initialize.dart.js:4386 ErrorEvent.fileName: http://localhost:63342/untitled4/build/web/index.bootstrap.initialize.dart.js
2015-12-22 15:19:35.932 index.bootstrap.initialize.dart.js:4386 ErrorEvent.message: Uncaught NoSuchMethodError: method not found: 'e9' (C.f.e9 is not a function)
2015-12-22 15:19:35.932 index.bootstrap.initialize.dart.js:4386 ErrorEvent.type: error
2015-12-22 15:19:35.932 index.bootstrap.initialize.dart.js:717 Uncaught NoSuchMethodError: method not found: 'e9' (C.f.e9 is not a function)
@sigmundch

This comment has been minimized.

Copy link
Member

commented Dec 22, 2015

Thanks for sending the repro test case, that was very helpful.

Seems that the problem only comes up when an existing zone wraps and rethrows the error. Polymer uses js-interop and binds callbacks to a zone. We can oversimplify that like this:

import 'dart:async';
import 'dart:html';
import 'dart:js' as js;

main() {
  window.onError.listen((e) => print(e.message));
  js.context['foo'] = Zone.current.bindCallback(callback);
  js.context.callMethod('foo', []);
}
callback() => throw 'hi there';

The JS interop bit is a bit of a red herring. Using an async microtask instead of body.onClick is enough to reproduce this in a couple lines:

import 'dart:async';
import 'dart:html';

main() {
  window.onError.listen((e) => print(e.message));
  new Future(callback);
}

callback() => throw 'hi there';

I'm going to investigate further to find the proper fix, but it would be nice if there was a more reliable way to get the stack trace than reading it out of a serialize message. It's not nice that if you get an exception that wasn't re-thrown, all the sudden you get fewer details (like my initial attempt to repro the problem).

@raphaeladam-wf

This comment has been minimized.

Copy link
Author

commented Dec 22, 2015

@sigmundch Thank you! We appreciate you taking time to look into this.

@sigmundch

This comment has been minimized.

Copy link
Member

commented Dec 22, 2015

OK - I think I have a better understanding of what's happening.

The regression was introduced in da8baac. We stopped wrapping exceptions when rethrowing in zones, then we weren't capturing the stack trace correctly and 5363e5c fixed that.

Because we don't wrap the rethrown exceptions, we can no longer override toString to include the extra stack trace. However, the stack is available and we attach it to the .stack property of the error. Unfortunately this makes the error harder to extract because it is not exposed through the Dart APIs - you need to use js-interop to get to it.

You can do this in multiple ways:

  • wrap the ErrorEvent object you get on onError and read the e.error.stack property from JS:
window.onError.listen((e) {
  var error = new JsObject.fromBrowserObject(e)['error'];
  if (error is JsObject) { // in Dartium error is just a String
    print('stack is here: ${error['stack']}');
  }
  print(e.message);
});
  • use js-interop to listen for on-error events in the first place (like we do on this test)

The good news is that this same logic is how you can to read out the stack trace when the original error was not rethrown (for example, my original attempt with document.body.onClick now will also print a nice stack trace from error['stack']).

I don't believe it makes sense to revert the changes in dart2js, since the new behavior is better at unifying how exceptions should be handled regardless of whether they are re-thrown. I'll wait to hear from you first to make sure the suggestions I propose here work for you before closing this bug, though.

/cc @lrhn (who made these changes in the firsplace), in case he has some additional insights/ideas to share.

One last note: the first change is in the stable channel 1.13.0, but the second change is not (it was picked up in 1.14.0). Without the latter, you'll get a stack trace from the rethrown location, rather than the original trace. If it's important for you guys to work on the stable channel, let us know and we'll file a request to merge the fix into the stable channel.

@travissanderson-wf

This comment has been minimized.

Copy link

commented Dec 23, 2015

We are probably stuck in the stable channel (for production and CI, but some of us use dev channel locally). If it isn't coming until 1.14 is in the stable channel, our workaround might just be to downgrade to 1.12 until 1.14 is stable. Thanks for looking into this.

@sigmundch

This comment has been minimized.

Copy link
Member

commented Jan 4, 2016

Thanks for letting me know - I have filed a request to merge the fix into 1.13 (see #25334) so hopefully you don't have to workaround this for much longer. I'm closing this issue since all there is left to do is covered by that other bug.

@sigmundch

This comment has been minimized.

Copy link
Member

commented Jan 6, 2016

Quick update - Bill just released a new stable channel version (1.13.2) that includes the fix. That should hopefully let you continue using the stable channel without downgrading.

@travissanderson-wf

This comment has been minimized.

Copy link

commented Jan 6, 2016

@sigmundch thanks for the quick turnaround, we will upgrade our systems to use 1.13.2 and verify all is well for us!

@raphaeladam-wf

This comment has been minimized.

Copy link
Author

commented Jan 6, 2016

Indeed! Thank you very much for the speedy response and resolution.

@travissanderson-wf

This comment has been minimized.

Copy link

commented Jan 6, 2016

It works! Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.