diff --git a/core-telemetry.cabal b/core-telemetry.cabal
--- a/core-telemetry.cabal
+++ b/core-telemetry.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           core-telemetry
-version:        0.1.9.2
+version:        0.1.9.3
 synopsis:       Advanced telemetry
 description:    This is part of a library to help build command-line programs, both tools and
                 longer-running daemons.
diff --git a/lib/Core/Telemetry/Observability.hs b/lib/Core/Telemetry/Observability.hs
--- a/lib/Core/Telemetry/Observability.hs
+++ b/lib/Core/Telemetry/Observability.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# OPTIONS_HADDOCK prune #-}
 
 {- |
@@ -163,12 +164,13 @@
 import Control.Concurrent.MVar (modifyMVar_, newMVar, readMVar)
 import Control.Concurrent.STM (atomically)
 import Control.Concurrent.STM.TQueue (writeTQueue)
+import qualified Control.Exception.Safe as Safe
 import Core.Data.Structures (Map, emptyMap, insertKeyValue)
 import Core.Encoding.Json
 import Core.Program.Arguments
 import Core.Program.Context
 import Core.Program.Logging
-import Core.System.Base (liftIO)
+import Core.System.Base (SomeException, liftIO)
 import Core.System.External (TimeStamp (unTimeStamp), getCurrentTimeNanoseconds)
 import Core.Telemetry.Identifiers
 import Core.Text.Rope
@@ -422,9 +424,12 @@
                     { currentDatumFrom = v2
                     }
 
-        -- execute nested program
-
-        result <- subProgram context2 action
+        -- execute nested program. We have to use try (c.f. catch) so that if
+        -- an exception has occurred we still enqueue the telemetry datum
+        -- before bailing out.
+        result :: Either SomeException a <-
+            Safe.try
+                (subProgram context2 action)
 
         -- extract the Datum as it stands after running the action, finalize
         -- with its duration, and send it
@@ -441,7 +446,9 @@
             writeTQueue tel (Just datum2')
 
         -- now back to your regularly scheduled Haskell program
-        pure result
+        case result of
+            Left e -> Safe.throw e
+            Right value -> pure value
 
 {- |
 Start a new trace. A random identifier will be generated.
