annotated-exception

Exceptions, with checkpoints and context.

https://github.com/parsonsmatt/annotated-exception#readme

Version on this page:0.3.0.2
LTS Haskell 23.27:0.3.0.4
Stackage Nightly 2025-07-12:0.3.0.4
Latest on Hackage:0.3.0.4

See all snapshotsannotated-exception appears in

BSD-3-Clause licensedbyMatt Parsons
Maintained by[email protected]
This version can be pinned in stack with:annotated-exception-0.3.0.2@sha256:ade1d768120f867b7c35f8c5531167e455306b7b75381a64875cea04d994fe10,1785

Module documentation for 0.3.0.2

Used by 2 packages inlts-23.17(full list with versions):

annotated-exception

This library provides a specialAnnotatedException type which allows you to decorate Haskell exceptions with additional information.This decoration is totally transparent, and even works with exceptions thrown outside of your application code.

To provide an annotation, you’d use the functioncheckpoint.This will attach the provided value to any exception that bubbles up through it.

import Control.Exception.Annotateddata MyException = MyException    deriving (Show, Exception)main :: IO ()main = do    checkpoint "Foo" $ do        throw MyException

When this program crashes, it will crash with anAnnotatedException that contains the annotation"Foo".

λ> checkpoint "Foo" $ throw MyException*** Exception: AnnotatedException {annotations = ["Foo"], exception = MyException}

These annotations survive, even if you catch and rethrow with a different exception.

data OtherException = OtherException    deriving (Show, Exception)woah :: IO ()woah = do    let        checkpointed =            checkpoint "Foo" (throw MyException)        handler MyException =            throw OtherException    checkpointed        `catch`            handler

Notice how thecheckpoint call doesn’t cover thethrow OtherException - the exception[Annotation] lives on the thrown exception itself, and this library’scatch function ensures that we don’t lose that context.

λ> (checkpoint "Foo" (throw MyException)) `catch` \MyException -> throw OtherException*** Exception: AnnotatedException {annotations = ["Foo"], exception = OtherException}

You can also attach aCallStack to any exception usingthrowWithCallStack.

Now, you’re about to report your exceptions, up nearmain.We can usetry in this module to always get the annotations.

main = do    eresult <- try $ myProgram    case eresult of        Left (AnnotatedException annotations exception) ->            reportException annotations exception        Right a ->            pure a

Changes

Changelog forannotated-exception

0.3.0.2

  • #32
    • Fixed the tests for GHC 9.10

0.3.0.1

  • #31
    • TheShow instance forAnnotatedException attempts to peek into theSomeException to provide a more useful exception type. Also gives theoutput ofshow.

0.3.0.0

  • #30
    • TheShow anddisplayException now render the annotated exception in amuch nicer way.

0.2.0.5

  • #27
    • Ensure thatflatten combinesCallStacks even when the callstack isattached manually.

0.2.0.4

  • #18
    • AddcheckpointCallStack even whencatch doesn’t catch anAnnotatedException

0.2.0.3

  • #17
    • AddHasCallStack tocatch andcatches

0.2.0.2

  • #14
    • DefineControl.Exception.Annotated.UnliftIO.checkpointCallStack withoutre-exporting theMonadCatch variant. Sigh.

0.2.0.1

  • #13
    • Fixed a bug inUnliftIO.catches where it would infinitely recurse.

0.2.0.0

  • #12
    • Removed theEq instance forAnnotation as well as theEq constraintinAnnC. These instances were only used for testing, and prevented thenatural use ofCallStack in a[Annotation].
    • Removed theEq instance forAnnotatedException as a consequence ofdropping theEq instance onAnnotation.
    • Removed thenew function. Usepure orexceptionWithCallStack instead.
    • Fixed a double-annotation bug incheckpointCallStackWith.
    • checkpointCallStack appends to the call-site list.
    • Pretty much everything now merges theCallStacks together.throwincludes aCallStack, as docheckpoint andcheckpointMany.

0.1.2.1

  • #8
    • There was a bug where catching or trying to catch an exception of thewrong type would trigger an infinite loop as thefromException methodkept digging and digging and would be unable to make things work out. ThefromException code no longer tries to flatten out these exceptions.However,toExceptiondoes flatten it, so all tests still pass.

0.1.2.0

  • #6
    • AddControl.Exception.Annotated.UnliftIO that usesMonadUnliftIOinstead ofMonadCatch andMonadThrow.
    • Actually exposecatches

0.1.1.0

  • #4
    • Addcatches
    • ReplaceControl.Exception.Safe.try withtry that can get anAnnotatedException e or a regular, un-Annotatede.

0.1.0.0

  • Initial Release