-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Debugger pauses on handled exceptions in async* methods as if they are unhandled #47985
Comments
//cc @DanTup both of the above issue seems to be reported against VS code, could you help debug the issue and root cause it. |
//cc @bkonyi |
@a-siva For me, it happened on intelliJ/AS, but I think it should be same as VS code. |
If I had to guess, a |
@a-siva @bkonyi maybe related to import 'dart:async';
Future<void> main() async {
try {
await _updateFile().toList();
} catch (e) {
print('Handled: $e');
}
}
Stream<String> _updateFile() async* {
yield* _manageResponse();
}
Stream<String> _manageResponse() async* {
throw 'error'; // The debugger will pause here, even though the error is going to be handled
} As far as I can see, the error is handled (it prints "Handled" and there's no unhandled error written to stderr or non-zero exit code). I can't reproduce it without the I don't know how to debug any further, but perhaps this simple repro helps :-) |
Actually, I can repro without import 'dart:async';
Future<void> main() async {
try {
await _manageResponse().toList();
} catch (e) {
print('Handled: $e');
}
}
Stream<String> _manageResponse() async* {
throw 'error'; // The debugger will pause here, even though the error is going to be handled
} |
@DanTup Any updates on this? |
I'm not familiar with the internals of the debugger so I think this would need to be looked at by someone on the VM team. |
It's really annoying since we receive many issues on Sentry. |
@aliyazdi75 how is this connected to Sentry? |
@aliyazdi75 I'm not familiar with Sentry, but if you're receiving runtime exception reports I think there may be two different issues here. My repro above is related to the debugger pausing on an exception that will be caught (despite being configured to only pause on uncaught exceptions). It only affects the debugger pausing and the error is otherwise handled correctly. If you're seeing runtime errors from users apps, I think that's another issue (and one that you can resolve separately to the issue my repro above covers). |
@aliyazdi75 this is not the same issue. this issue is about the debugger (or more specifically about interaction between exceptions from |
@mraleph I don't think that's a separate issue. I reported what I observed for adding more information regarding this issue. I don't add misinformation. I have no idea how Sentry report that |
@aliyazdi75 again, I suggest you to review your code - these two issues are unrelated. Sentry installs a bunch of error listeners (e.g. |
Correct me if I'm wrong, but I think this is caused by #46318. The debugger looks for exception handlers by checking the frames available in the stack trace Lines 803 to 805 in 0304832
A frame corresponding to This can be observed by running the VM with Lines 799 to 802 in 0304832
|
@derekxu16 The failure on Danny's example it is not related to #46318, but you are correct that it related to awaiter stack not reaching the main. The reason it does not reach main is because This can either be fixed by rewriting |
@mraleph do you think flutter/flutter#129121 could be related? See my comment at flutter/flutter#129121 (comment) for a simple repro and VM Service log. |
@DanTup it's a similar issue. The actual exception is thrown when stack trace looks like this:
|
Got it, thanks! If I understand correctly, this means the proposal in flutter/devtools#5883 would also not help here (because the exception looks completely uncaught, rather than just being caught in non-debuggable file which that proposal would handle differently)? |
The main contribution of this CL is unification of disparate handling of various functions like `Future.timeout`, `Future.wait`, `_SuspendState.createAsyncCallbacks` and `_SuspendState._createAsyncStarCallback` into a single `@pragma('vm:awaiter-link')` which allows Dart developers to specify where awaiter unwinder should look for the next awaiter. For example this allows unwinding to succeed for the code like this: Future<int> outer(Future<int> inner) { @pragma('vm:awaiter-link') final completer = Completer<int>(); inner.then((v) => completer.complete(v)); return completer.future; } This refactoring also ensures that we preserve information (including Function & Code objects) required for awaiter unwinding across all modes (JIT, AOT and AOT with DWARF stack traces). This guarantees users will get the same information no matter which mode they are running in. Previously we have been disabling awaiter_stacks tests in some AOT modes - which led to regressions in the quality of produced stacks. This CL also cleans up relationship between debugger and awaiter stack returned by StackTrace.current - which makes stack trace displayed by debugger (used for stepping out and determinining whether exception is caught or not) and `StackTrace.current` consistent. Finally we make one user visible change to the stack trace: awaiter stack will no always include intermediate listeners created through `Future.then`. Previously we would sometimes include these listeners at the tail of the stack trace, which was inconsistent. Ultimately this means that code like this: Future<int> inner() async { await null; // asynchronous gap print(StackTrace.current); // (*) return 0; } Future<int> outer() async { int process(int v) { return v + 1; } return await inner().then(process); } void main() async { await outer(); } Produces stack trace like this: inner <asynchronous suspension> outer.process <asynchronous suspension> outer <asynchronous suspension> main <asynchronous suspension> And when stepping out of `inner` execution will stop at `outer.process` first and the next step out will bring execution to `outer` next. Fixes #52797 Fixes #52203 Issue #47985 TEST=ci Bug: b/279929839 CoreLibraryReviewExempt: CL just adds @pragma to facilitate unwinding Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-dwarf-linux-product-x64-try Change-Id: If377d5329d6a11c86effb9369dc603a7ae616fe7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311680 Reviewed-by: Alexander Markov <[email protected]> Commit-Queue: Slava Egorov <[email protected]>
Just to add another example where this happens. Trying to use the flutter_map package from vscode in Windows (windows-x64) debug mode. Created a new application using the "Flutter: New Project", Application (Empty), entered: With only "uncaught exceptions" ticked I also get a SocketException "Failed host lookup: 'tile.openstreetmap.org'" "The requested name is valid, but no data of the requested type was found.", errno = 11004 in L520 of dart:io-patch\socket_patch.dart (with same stacktrace shown by @mraleph) Also runs fine in both debug and run from flutter run command (and build). Unchecking both "All" and "Uncaught" breakpoints options in the debugger lets the program run without issue. I'm using stable Flutter 3.13.0 (I've not tried on earlier versions) Commented originally in issue flutter/flutter#129121 |
I think it's related, but that CP was in the previous stable version and complaints in that version were that the debugger paused if "All Exceptions" was ticked. In last weeks stable, the debugger is pausing with only "uncaught exceptions" ticked which is significantly worse. I've opened #53334 specifically for this issue to avoid confusing it with this one (which seems to be related to |
This is really confusing me, i write a API call using Dio, and when i try to cal it without backend server running, vscode will pause my app and show me a uncaught exception |
@laeo if this isn't in an async* method, it's probably not related to this issue. There are some other similar open issues (such as #53334), although it's not clear to me what the expected behaviour is - if your backend server being down results in an uncaught exception, this sounds like behaviour I would expect. If you think it's a bug (because something is catching the exception) and it doesn't seem like the same issue described in #53334, please file a new issue with a small (but complete) code example that can be used to reproduce the issue. Thanks! |
Is there still no fix for this? |
The fix has landed in the main branch and we should have a fix in stable via the hotfix release next week. |
Will the next new stable version fix this issue? |
Still exists in Flutter Channel stable, 3.13.9. the bug is annoying |
I can also confirm that this happen on stable, 3.13.9. Here is my bug report with an example of code that can be used: cfug/dio#2025 but apparently there is not much Dio can do themselves to have it solved. The uncaught exception issue starts in a function below @internal
static Future<T> listenCancelForAsyncTask<T>(
CancelToken? cancelToken,
Future<T> future,
) {
return Future.any([
if (cancelToken != null) cancelToken.whenCancel.then((e) {
throw e;
}),
future,
]);
} |
@tomekit I'm not sure this is the same issue. This issue relates to the debugger pausing on an extension that will be caught, even if settings are such that only uncaught exceptions should pause (specifically in In your report, it sounds like the application behaviour is unexpected (and that nothing happens):
It's not clear to me if nothing is happening because the debugger has paused, or if you're just seeing unexpected runtime behaviour (that is unrelated to the debugger). If the latter, then I don't think it's the same issue. Edit: I've updated the title to try and make it a little clearer |
I am experiencing completely the same issue. In my case, this happens using
And then I call it like this somewhere in the code:
Sadly, when there goes smth wrong on BE side, for example the endpoint does not exist, or return error, the debugger pauses on following line, even though the exception is catcher later on:
|
@HE-LU can you provide a small complete sample that can be used to reproduce this? If you're not inside an |
Hi @DanTup,
I've improved my report and wording little bit (cfug/dio#2025). It seems that I've incorrectly assumed that just because there is an issue with the debugger, it's also likely what "breaks" the cancellation (implemented by throwing exception from the async*)... and even though I wouldn't be surprised if these issues are somewhat related I probably shouldn't mix these two and derive any meaningful conclusions. |
Hi again @DanTup, I've decided to play around and built an example to demonstrate an issue which I believe to be incorrect Dart behavior. This issue is present regardless if I ran the app in debug/release mode and no debugger is involved here. Please find buttons on the right side. The "red" ones indicate behavior which I consider not expected. I am running: Flutter 3.13.9 and running/building app on Ubuntu 23.04. |
@tomekit this issue is specifically about whether the debugger pauses execution and not about the runtime behaviour. If your application is not doing as you expect (for example if you "Start without Debugging" or disable breaking on exceptions), that is not the same issue. That said, I think the few examples I checked in your repro are working as intended. For example: FloatingActionButton(
onPressed: () async {
_manageResponse();
},
tooltip: 'Uncaught exception test from async* (no effect !)',
child: const Icon(Icons.error, color: Colors.redAccent),
),
void main(List<String> arguments) async {
try {
foo(); // no await here
} catch (e) {
print('never executes');
}
}
Future<void> foo() async {
throw 'error';
} If you remove |
Is there any update here? It still happens in Flutter 3.16.5. |
I just had to downgrade all the way to Flutter 3.10.5 to get rid of this. This is directly affecting all error handling on Flutter's biggest HTTP package (Dio). Can we please get some traction on this issue? |
The Dio cancellation exception problem was fixed by 0ea5013. And the remaining cases will be fixed by https://dart-review.googlesource.com/c/sdk/+/322720 |
@mraleph thank you! any idea on when should we expect this fix to be released? |
The first one should already be on Flutter master channel - so you can test it. |
This issue continues #37953 and #47692.
Regarding this issue for
cached_network_image
plugin, this problem still persists.This is a reproducible Gist. As you can see, with defining an
errorWidget
, the exceptions should be handled but the debugger throws oncached_network_image
exceptions only, not all flutter exceptions.flutter doctor -v
The text was updated successfully, but these errors were encountered: