{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreifigbx7salncu7fdlmzvojncu4tl6lrqk2fh6c27xwageoeyau5oa",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mlxlbc2wpet2"
},
"path": "/t/exception-annotations-lay-of-the-land/14056#post_5",
"publishedAt": "2026-05-16T08:48:11.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"toException",
"rethrowIO",
"throwIO",
"SomeException",
"ExceptionWithContext"
],
"textContent": "I don’t know why the invariant that toException must drop the context was added. Maybe it was added to make the behaviour of existing exception-rethrowing code outside of base more uniform?\n\nTo recap. In modern base, we have that specialized rethrowIO function that does the right thing™ to propagate the context when rethrowing. All rethrowing code in base will use it. However, _outside_ of base, we’ll have lots of code like\n\n\n catchAndThrow :: IO a -> IO a\n catchAndThrow = handle $ \\(e :: SomeException) -> throwIO e\n\n catchAndThrowIOException :: IO a -> IO a\n catchAndThrowIOException = handle $ \\(e :: IOException) -> throwIO e\n\n\nthat performs rethrows using the old throwIO. Rethrows of SomeException, but also rethrows of some concrete exception like `IOException`.\n\nIf we don’t require `toException` to drop the exception context:\n\n * The exception that comes out of `catchAndThrow` will have two backtraces, the one from the original `SomeException` and the one added by the `throwIO`. Is that bad? Perhaps we could tolerate it and, by convention, assume that the last backtrace in the exception context is the original one. But perhaps it would confuse tooling like the new debugger. As code begins to migrate to `rethrowIO`, double backtraces would become rarer.\n\n * The exception that comes out of `catchAndThrowIOException` will have only one backtrace, the one added by the `throwIO`, because concrete exceptions don’t carry a context. We would need to switch to `rethrowIO` to keep the original backtrace. Is that lack of uniformity with respect to `SomeException` bad?\n\n\n\n\nAlternatively, if we require `toException` to drop the exception context, in both `catchAndThrow` and `catchAndThrowIOException` the outgoing exception will only have the context added by the `throwIO`. Again, we would need to switch to `rethrowIO` to keep the original backtrace instead. And I would prefer `toException` to drop the context _even for ExceptionWithContext_ , and have that separate `toExceptionPreservingContext` function mentioned earlier.\n\n * `SomeException` and `ExceptionWithContext` rethrows with `throwIO` won’t include the original context. That would admittedly be a bit unintuitive.\n * But it’s more uniform with re-throwing other types of exceptions using `throwIO`. A single “if you want the original context, switch to `rethrowIO`!” slogan applicable in all cases, instead of “well, you can switch to `rethrowIO`, but in the particular case of `SomeException` and `ExceptionWithContext` you might not need to do so, it depends…”\n * Duplicate backtraces won’t ever happen.\n\n",
"title": "Exception Annotations: Lay of the Land"
}