From the `withContext` docs: > The resulting c...
# coroutines
e
From the
withContext
docs:
The resulting context for the block is derived by merging the current
coroutineContext
with the specified
context
using
coroutineContext + context
(see
CoroutineContext.plus
).
From the
CoroutineContext.plus
docs:
Returns a context containing elements from this context and elements from other
context
. The elements from this context with the same key as in the other one are dropped.
From these docs I conclude that any
CoroutineExceptionHandler
in the
context
in
withContext(context)
call replaces the one from the parent scope of
withContext
. So why does @Manuel Vivo write in his excellent article (https://medium.com/androiddevelopers/coroutines-patterns-for-work-that-shouldnt-be-cancelled-e26c40f142ad):
CoroutineExceptionHandlers don’t work as you’d expect when the context is used in withContext since the exception will be re-thrown.
So how come that a thrown exception is handled by the parent exception handler (which might rethrow it) , instead of handled by the overridden exception handler?
This example shows that the outer context (as described by Manuel's article) handles the exception: https://pl.kotl.in/ZyflFSKTB But as a naive user I'd expect my other exception handler to handle the exception
a
I suspect it’s because withContext doesn’t introduce a new Job - so the stack simply unwinds past it when throwing an exception, as opposed to causing a job cancellation
e
We’ve recently improved the docs on
CoroutineExceptionHandler
. Not yet in master. It should now better explain the details and stress the fact that it is the only used for top-level uncaught exceptions. (Wrong link. See right one below)
e
Thanks! 🙂
Would it be valuable to update the
withContext
docs too? Or maybe take this a step further and structure the
CoroutineContext
type hierarchy a bit more transparently? For example: a
CoroutineExceptionHandler
cannot be replaced (at least not the one in the root scope). A
Job
should not (or never?) be passed to
launch
or
async
. And there are some other finicky details about what is possible, but doesn't work as it might seem, or shouldn't be done at all. Could a bit more sophisticated type structure protect users against misuse/mistakes?