diff --git a/App/main.cpp b/App/main.cpp
index 0b853e97d747d9983411c4cf357bd24553f36e1f..9bea2b0ac4ac08ed6cc9ba3679ea027fcc2d0bc7 100644
--- a/App/main.cpp
+++ b/App/main.cpp
@@ -28,6 +28,15 @@
 #include <QMetaType>
 #include <QtGlobal>
 
+auto guiFailedAssertion = [](std::string msg) {
+#ifdef BA_DEBUG
+    std::cerr << "FATAL (catched in debug mode): " << msg << std::endl;
+    std::raise(11); // abort so that we can inspect the backtrace
+#else
+    qFatal(msg.c_str());
+#endif
+};
+
 int main(int argc, char* argv[])
 {
     ApplicationOptions options(argc, argv);
@@ -46,7 +55,7 @@ int main(int argc, char* argv[])
     ApplicationSettings applicationSettings;
 
     qInstallMessageHandler(messageHandler);
-    failedAssertion = [](std::string msg) { qFatal(msg.c_str()); };
+    failedAssertion = guiFailedAssertion;
 
     register1DDataLoaders();
 
diff --git a/Base/Util/Assert.cpp b/Base/Util/Assert.cpp
index 57712bfdc847b0f8b59a63c781f0f4f41081b355..39ede6f9478faede379e3e8a51f5155c75d076cd 100644
--- a/Base/Util/Assert.cpp
+++ b/Base/Util/Assert.cpp
@@ -13,14 +13,7 @@
 //  ************************************************************************************************
 
 #include "Base/Util/Assert.h"
-#include <csignal>
-#include <iostream>
 
 std::function<void(std::string)> failedAssertion = [](std::string msg) {
-#ifdef BA_DEBUG
-    std::cerr << msg << std::endl;
-    std::raise(11); // abort so that we can inspect the backtrace
-#else
     throw std::runtime_error(msg);
-#endif
 };
diff --git a/Base/Util/Assert.h b/Base/Util/Assert.h
index 7e8a61a4e75aca38a5ca82b69bf063d7837f99fc..1c4a66c3563507d605853a994033d8764050e2ee 100644
--- a/Base/Util/Assert.h
+++ b/Base/Util/Assert.h
@@ -20,23 +20,46 @@
 
 #include "Wrap/WinDllMacros.h"
 #include <functional>
-#include <sstream>
-#include <stdexcept>
 #include <string>
 
 // Function called upon failed assert; set in Assert.cpp, overriden by GUI.
 extern BA_BASE_API_ std::function<void(std::string)> failedAssertion;
 
-// ASSERT must be declared as a macro, not a function, in order for the error
-// message to correctly report the source line where the assertion failed.
+// ASSERT macro: terminate if condition is false.
+//
+// Implementation notes:
+// - Must be declared as a macro, not a function, so that we can use preprocessor
+//   macros for informative error messages.
+// - Must terminate with a throw statement to  prevent compiler warning -Wreturn-type.
+// - In the GUI, the function pointer failedAssertion will be reset to call qFatal,
+//   which then pops up a message window (as defined by qInstallMessageHandler).
+// - No direct call to qFatal here, because we do not want core to depend on Qt,
+//   lest Python wheel becomes too difficult.
+
+#ifdef BA_DEBUG
 
+#include <csignal>
+#include <iostream>
+#define ASSERT(condition)                                                                          \
+    if (!(condition)) {                                                                            \
+        std::cerr << "Assertion " << (#condition) << " failed in " << __FILE__ << ", line "        \
+                  << __LINE__ << std::endl;                                                        \
+        std::raise(SIGTERM); /* abort so that we can inspect the backtrace */                      \
+        throw std::runtime_error("Assertion failed ... and we should never get here");             \
+    }
+
+#else
+
+#include <sstream>
+#include <stdexcept>
 #define ASSERT(condition)                                                                          \
     if (!(condition)) {                                                                            \
         std::stringstream msg;                                                                     \
         msg << "Assertion " << (#condition) << " failed in " << __FILE__ << ", line " << __LINE__; \
         failedAssertion(msg.str());                                                                \
-        /* The following throw is needed to prevent compiler warning -Wreturn-type */              \
         throw std::runtime_error("Assertion failed ... and we should never get here");             \
     }
 
+#endif // BA_DEBUG
+
 #endif // BORNAGAIN_BASE_UTIL_ASSERT_H