You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ASyncException.hs: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
yoto
HasCallStack backtrace:
throwIO, called at ./Control/Concurrent/Async/Internal.hs:630:24 in async-2.2.5-50rpfAJ7BEc1o5OswtTMUN:Control.Concurrent.Async.Internal
Especially:
The backtrace points to the internal of async, completly losing the "real" and relevant backtrace
The exception annoattion is lost
If run without the async "wrapping", we get instead:
ASyncException.hs: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
yoto
Ann "bonjour"
HasCallStack backtrace:
error, called at ASyncException.hs:15:3 in main:Main
asyncTask, called at ASyncException.hs:24:3 in main:Main
With annotation and backtrace.
This could be fixed by using rethrowIO instead of throw everywhere an exception is rethrown in async. See the attached MR which can be used as a proof of concept. A bit of discussion may be necessary to know if we want to add a WhileHandling context before rethrowing.
Note that there is the additional issue that throwSTM does not attach backtrace information, in particular waitSTM rethrows an exception using throwSTM so it gets no context at all.
As a rule of thumb, anywhere an exception is caught and rethrown, use rethrowIO rather than throwIO. We probably also need rethrowSTM for this use case.
*** Exception: Exc' "yoto"
While handling Exc' "yoto"
Ann "bonjour"
HasCallStack backtrace:
throwIO, called at test/test-async.hs:39:3 in async-2.2.5-inplace-test-async:Main
asyncTask, called at test/test-async.hs:46:13 in async-2.2.5-inplace-test-async:Main
Here I'm annoyed by:
The present of While handling, which is added by the wait call, but that's still unclear why to me.
The CallStack does NOT show anything related to the wait location, it only shows the callsite for asyncTask.
I think the correct solution would be to add some sort of While waiting at exception annotation on wait, adding another HasCallStack backtrace for the wait location ?
I'm rather opposed to adding HasCallStack anywhere in the core API. We already have a compile-time flag debug-auto-label that adds HasCallStack and that's where I think it should stay.
Activity
mpickering commentedon Jan 8, 2026
It would be good to do a release which implements this change. You could get better backtraces when using
asyncif this was implemented.mpickering commentedon Jan 8, 2026
Note that there is the additional issue that
throwSTMdoes not attach backtrace information, in particularwaitSTMrethrows an exception usingthrowSTMso it gets no context at all.As a rule of thumb, anywhere an exception is caught and rethrown, use
rethrowIOrather thanthrowIO. We probably also needrethrowSTMfor this use case.guibou commentedon Jan 31, 2026
(Sorry, this was a comment intended for #165)
I'm a bit annoyed.
Take this code sample:
The current output is:
Here I'm annoyed by:
While handling, which is added by thewaitcall, but that's still unclear why to me.waitlocation, it only shows the callsite forasyncTask.I think the correct solution would be to add some sort of
While waiting atexception annotation onwait, adding anotherHasCallStackbacktrace for thewaitlocation ?simonmar commentedon Feb 3, 2026
I'm rather opposed to adding
HasCallStackanywhere in the core API. We already have a compile-time flagdebug-auto-labelthat addsHasCallStackand that's where I think it should stay.