diff --git a/Core/include/ACTS/Utilities/BinningData.hpp b/Core/include/ACTS/Utilities/BinningData.hpp
index 1b63dab013c47f6fa20e0cf566b7a52677281791..edc4cbd57496260ef6ac068de37e3ee21a7468b6 100644
--- a/Core/include/ACTS/Utilities/BinningData.hpp
+++ b/Core/include/ACTS/Utilities/BinningData.hpp
@@ -19,6 +19,7 @@
 #include <vector>
 #include "ACTS/Utilities/BinningType.hpp"
 #include "ACTS/Utilities/Definitions.hpp"
+#include "ACTS/Utilities/ThrowAssert.hpp"
 
 namespace Acts {
 
@@ -145,7 +146,7 @@ public:
     , m_functionPtr(nullptr)
   {
     // assert a no-size case
-    assert(m_boundaries.size() > 1);
+    throw_assert(m_boundaries.size() > 1, "Must have more than one boundary");
     min = m_boundaries[0];
     max = m_boundaries[m_boundaries.size() - 1];
     // set to equidistant search
@@ -373,7 +374,8 @@ public:
   search(float value) const
   {
     if (zdim) return 0;
-    assert(m_functionPtr != nullptr);
+    throw_assert(m_functionPtr != nullptr,
+                 "Search function pointer is nullptr");
     return (!subBinningData) ? (*m_functionPtr)(value, *this)
                              : searchWithSubStructure(value);
   }
diff --git a/Core/include/ACTS/Utilities/ThrowAssert.hpp b/Core/include/ACTS/Utilities/ThrowAssert.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c52e814fafa8bcee6514bf54162b66a92d461a50
--- /dev/null
+++ b/Core/include/ACTS/Utilities/ThrowAssert.hpp
@@ -0,0 +1,90 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2018 ACTS project team
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef ACTS_UTILITIES_THROWASSERT_H
+#define ACTS_UTILITIES_THROWASSERT_H 1
+
+#include <exception>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+namespace Acts {
+/// @brief Exception type for assertion failures
+/// This class captures the information available to the throw_assert macro
+class AssertionFailureException : public std::exception
+{
+public:
+  /// @brief Class which allows to use the << operator to assemble a string
+  class StreamFormatter
+  {
+  private:
+    std::ostringstream stream;
+
+  public:
+    /// @brief Converts to string
+    operator std::string() const { return stream.str(); }
+
+    /// @brief Stream operator which takes everything and forwards
+    ///        it to the stringstream.
+    /// @tparam T type of anything
+    /// @param value const ref to anything
+    template <typename T>
+    StreamFormatter&
+    operator<<(const T& value)
+    {
+      stream << value;
+      return *this;
+    }
+  };
+
+  /// @brief Construct an assertion failure exception, captures macro info
+  /// @param expression The expression being asserted
+  /// @param file The current file
+  /// @param line The current line
+  /// @param msg The message to print if assertion fails
+  AssertionFailureException(std::string        expression,
+                            std::string        file,
+                            int                line,
+                            const std::string& msg)
+  {
+    std::ostringstream os;
+
+    if (!msg.empty()) {
+      os << msg << ": ";
+    }
+
+    os << "Assertion '" << expression << "'";
+
+    os << " failed in file '" << file << "' line " << line;
+    report = os.str();
+  }
+
+  /// The assertion message
+  virtual const char*
+  what() const throw()
+  {
+    return report.c_str();
+  }
+
+private:
+  std::string report;
+};
+
+}  // namespace Acts
+
+#define throw_assert(EXPRESSION, MESSAGE)                                      \
+  if (!(EXPRESSION)) {                                                         \
+    throw Acts::AssertionFailureException(                                     \
+        #EXPRESSION,                                                           \
+        __FILE__,                                                              \
+        __LINE__,                                                              \
+        (Acts::AssertionFailureException::StreamFormatter() << MESSAGE));      \
+  }
+
+#endif
diff --git a/Core/src/Surfaces/ConeSurface.cpp b/Core/src/Surfaces/ConeSurface.cpp
index 1f410b66a536539bde0e2d0585160fdfebbf4613..96858a9ed41f632c34538aa4377faeb2f5df19af 100644
--- a/Core/src/Surfaces/ConeSurface.cpp
+++ b/Core/src/Surfaces/ConeSurface.cpp
@@ -17,6 +17,7 @@
 #include <iomanip>
 #include <iostream>
 
+#include "ACTS/Utilities/ThrowAssert.hpp"
 #include "ACTS/Utilities/detail/RealQuadraticEquation.hpp"
 
 Acts::ConeSurface::ConeSurface(const ConeSurface& other)
@@ -52,7 +53,7 @@ Acts::ConeSurface::ConeSurface(std::shared_ptr<const Transform3D> htrans,
                                std::shared_ptr<const ConeBounds>  cbounds)
   : Surface(htrans), m_bounds(cbounds)
 {
-  assert(cbounds);
+  throw_assert(cbounds, "ConeBounds must not be nullptr");
 }
 
 Acts::ConeSurface::~ConeSurface()
diff --git a/Core/src/Surfaces/CylinderSurface.cpp b/Core/src/Surfaces/CylinderSurface.cpp
index 38b5243fc9a65e5e86fff5d426f3335ed80eac11..ab502c3e4995675a620e87011db4f42f89837caa 100644
--- a/Core/src/Surfaces/CylinderSurface.cpp
+++ b/Core/src/Surfaces/CylinderSurface.cpp
@@ -17,6 +17,7 @@
 #include <iomanip>
 #include <iostream>
 
+#include "ACTS/Utilities/ThrowAssert.hpp"
 #include "ACTS/Utilities/detail/RealQuadraticEquation.hpp"
 
 Acts::CylinderSurface::CylinderSurface(const CylinderSurface& other)
@@ -64,7 +65,7 @@ Acts::CylinderSurface::CylinderSurface(
     std::shared_ptr<const CylinderBounds> cbounds)
   : Surface(htrans), m_bounds(cbounds)
 {
-  assert(cbounds);
+  throw_assert(cbounds, "CylinderBounds must not be nullptr");
 }
 
 Acts::CylinderSurface::~CylinderSurface()
diff --git a/Core/src/Surfaces/DiamondBounds.cpp b/Core/src/Surfaces/DiamondBounds.cpp
index 6beb1e2650215220dd908bf77471ac8fff5f7cc1..7713f5d8b0a7ff6fb1780da75091e627d629047b 100644
--- a/Core/src/Surfaces/DiamondBounds.cpp
+++ b/Core/src/Surfaces/DiamondBounds.cpp
@@ -11,6 +11,7 @@
 ///////////////////////////////////////////////////////////////////
 
 #include "ACTS/Surfaces/DiamondBounds.hpp"
+#include "ACTS/Utilities/ThrowAssert.hpp"
 
 #include <cmath>
 #include <iomanip>
@@ -29,8 +30,8 @@ Acts::DiamondBounds::DiamondBounds(double minhalex,
   , m_boundingBox(std::max(std::max(minhalex, medhalex), maxhalex),
                   std::max(haley1, haley2))
 {
-  assert((minhalex <= medhalex) && "Hexagon must be a convex polygon");
-  assert((maxhalex <= medhalex) && "Hexagon must be a convex polygon");
+  throw_assert((minhalex <= medhalex), "Hexagon must be a convex polygon");
+  throw_assert((maxhalex <= medhalex), "Hexagon must be a convex polygon");
 }
 
 Acts::DiamondBounds::~DiamondBounds()
diff --git a/Core/src/Surfaces/DiscSurface.cpp b/Core/src/Surfaces/DiscSurface.cpp
index 0871129e58aa708afd8b1ebb81a32d349154598c..0dc1a097a558d90043ff58bdb437e413fe0a807f 100644
--- a/Core/src/Surfaces/DiscSurface.cpp
+++ b/Core/src/Surfaces/DiscSurface.cpp
@@ -20,6 +20,7 @@
 #include "ACTS/Surfaces/InfiniteBounds.hpp"
 #include "ACTS/Surfaces/RadialBounds.hpp"
 #include "ACTS/Utilities/Definitions.hpp"
+#include "ACTS/Utilities/ThrowAssert.hpp"
 
 Acts::DiscSurface::DiscSurface(const DiscSurface& other)
   : Surface(other), m_bounds(other.m_bounds)
@@ -69,7 +70,7 @@ Acts::DiscSurface::DiscSurface(std::shared_ptr<const DiscBounds> dbounds,
                                const Identifier&                 identifier)
   : Surface(detelement, identifier), m_bounds(nullptr)
 {
-  assert(dbounds);
+  throw_assert(dbounds, "nullptr as DiscBounds");
 }
 
 Acts::DiscSurface::~DiscSurface()
diff --git a/Core/src/Surfaces/LineSurface.cpp b/Core/src/Surfaces/LineSurface.cpp
index 802bdf536135c02bf9a9ce71dd0caeb43f0182a7..6dd3f789876b674e3677bd03f814028d63aaf37e 100644
--- a/Core/src/Surfaces/LineSurface.cpp
+++ b/Core/src/Surfaces/LineSurface.cpp
@@ -16,6 +16,8 @@
 #include <iomanip>
 #include <iostream>
 
+#include "ACTS/Utilities/ThrowAssert.hpp"
+
 Acts::LineSurface::LineSurface(std::shared_ptr<const Transform3D> htrans,
                                double                             radius,
                                double                             halez)
@@ -34,7 +36,7 @@ Acts::LineSurface::LineSurface(std::shared_ptr<const LineBounds> lbounds,
                                const Identifier&                 id)
   : Surface(detelement, id), m_bounds(lbounds)
 {
-  assert(lbounds);
+  throw_assert(lbounds, "LineBounds must not be nullptr");
 }
 
 Acts::LineSurface::LineSurface(const LineSurface& other)
diff --git a/Core/src/Surfaces/PlaneSurface.cpp b/Core/src/Surfaces/PlaneSurface.cpp
index aae8944084dcb477848fe8f8da07022bbaa81e57..1f89f90e0b85c6b50138e4ecdefd8fc8d1ef86f5 100644
--- a/Core/src/Surfaces/PlaneSurface.cpp
+++ b/Core/src/Surfaces/PlaneSurface.cpp
@@ -19,6 +19,7 @@
 #include "ACTS/Surfaces/InfiniteBounds.hpp"
 #include "ACTS/Surfaces/RectangleBounds.hpp"
 #include "ACTS/Utilities/Identifier.hpp"
+#include "ACTS/Utilities/ThrowAssert.hpp"
 
 Acts::PlaneSurface::PlaneSurface(const PlaneSurface& other)
   : Surface(other), m_bounds(other.m_bounds)
@@ -60,7 +61,7 @@ Acts::PlaneSurface::PlaneSurface(std::shared_ptr<const PlanarBounds> pbounds,
   : Surface(detelement, identifier), m_bounds(pbounds)
 {
   /// surfaces representing a detector element must have bounds
-  assert(pbounds);
+  throw_assert(pbounds, "PlaneBounds must not be nullptr");
 }
 
 Acts::PlaneSurface::PlaneSurface(std::shared_ptr<const Transform3D>  htrans,
diff --git a/Tests/Surfaces/ConeSurfaceTests.cpp b/Tests/Surfaces/ConeSurfaceTests.cpp
index 3640db95dc142a1e6e6dd00e5b60e4379e686092..9ab124c93cf31f36b602b117ad5a2cacf06c4ff6 100644
--- a/Tests/Surfaces/ConeSurfaceTests.cpp
+++ b/Tests/Surfaces/ConeSurfaceTests.cpp
@@ -71,6 +71,10 @@ namespace Test {
     /// Copied and transformed
     ConeSurface copiedTransformedConeSurface(coneSurfaceObject, *pTransform);
     BOOST_TEST(copiedTransformedConeSurface.type() == Surface::Cone);
+
+    /// Construct with nullptr bounds
+    BOOST_CHECK_THROW(ConeSurface nullBounds(nullptr, nullptr),
+                      AssertionFailureException);
   }
   //
   /// Unit test for testing ConeSurface properties
diff --git a/Tests/Surfaces/CylinderSurfaceTests.cpp b/Tests/Surfaces/CylinderSurfaceTests.cpp
index 244c33622cbe97a79bd016085ac2d5cf00926f0a..86391bae3c3c531ca678b9454b20139fa73d5ee0 100644
--- a/Tests/Surfaces/CylinderSurfaceTests.cpp
+++ b/Tests/Surfaces/CylinderSurfaceTests.cpp
@@ -68,6 +68,10 @@ namespace Test {
     CylinderSurface copiedTransformedCylinderSurface(cylinderSurfaceObject,
                                                      *pTransform);
     BOOST_TEST(copiedTransformedCylinderSurface.type() == Surface::Cylinder);
+
+    /// Construct with nullptr bounds
+    BOOST_CHECK_THROW(CylinderSurface nullBounds(nullptr, nullptr),
+                      AssertionFailureException);
   }
   //
   /// Unit test for testing CylinderSurface properties
diff --git a/Tests/Surfaces/DetectorElementStub.hpp b/Tests/Surfaces/DetectorElementStub.hpp
index 10d833dfa4b283b404d70bf08521cffb7def0c30..047e03ec8341819c6cfece60119a36174ab9fe3c 100644
--- a/Tests/Surfaces/DetectorElementStub.hpp
+++ b/Tests/Surfaces/DetectorElementStub.hpp
@@ -38,6 +38,8 @@ class LineBounds;
 class DetectorElementStub : public DetectorElementBase
 {
 public:
+  DetectorElementStub() : DetectorElementBase() {}
+
   /// Constructor for single sided detector element
   /// - bound to a Plane Surface
   ///
diff --git a/Tests/Surfaces/DiamondBoundsTests.cpp b/Tests/Surfaces/DiamondBoundsTests.cpp
index 627250b128fda78b37846affc7925f06c15fc448..b0b2fb3c3a30399121427947d0f37bde756a4b1b 100644
--- a/Tests/Surfaces/DiamondBoundsTests.cpp
+++ b/Tests/Surfaces/DiamondBoundsTests.cpp
@@ -44,6 +44,14 @@ namespace Test {
     DiamondBounds original(minHalfX, midHalfX, maxHalfX, halfY1, halfY2);
     DiamondBounds copied(original);
     BOOST_TEST(copied.type() == SurfaceBounds::Diamond);
+
+    // invalid inputs
+    BOOST_CHECK_THROW(
+        DiamondBounds db(midHalfX, minHalfX, maxHalfX, halfY1, halfY2),
+        AssertionFailureException);
+    BOOST_CHECK_THROW(
+        DiamondBounds db(minHalfX, maxHalfX, midHalfX, halfY1, halfY2),
+        AssertionFailureException);
   }
   /// Unit tests for DiamondBounds properties
   BOOST_AUTO_TEST_CASE(DiamondBoundsProperties)
diff --git a/Tests/Surfaces/DiscSurfaceTests.cpp b/Tests/Surfaces/DiscSurfaceTests.cpp
index 797598b7618c2f8e6a1241022da323b52f664dc9..d239397d43c2a376738dfdc2b9782bee770a12f3 100644
--- a/Tests/Surfaces/DiscSurfaceTests.cpp
+++ b/Tests/Surfaces/DiscSurfaceTests.cpp
@@ -64,6 +64,12 @@ namespace Test {
     //
     /// Copied and transformed DiscSurface
     BOOST_CHECK_NO_THROW(DiscSurface(anotherDiscSurface, *pTransform));
+
+    /// Construct with nullptr bounds
+    Identifier          id;
+    DetectorElementStub detElem;
+    BOOST_CHECK_THROW(DiscSurface nullBounds(nullptr, detElem, id),
+                      AssertionFailureException);
   }
 
   /// Unit tests of all named methods
diff --git a/Tests/Surfaces/LineSurfaceTests.cpp b/Tests/Surfaces/LineSurfaceTests.cpp
index e6093f2cc3dedf911bd898b407504bb914767558..eeb5a3acca0490d244f67f06149f3dd018c91ddb 100644
--- a/Tests/Surfaces/LineSurfaceTests.cpp
+++ b/Tests/Surfaces/LineSurfaceTests.cpp
@@ -65,6 +65,13 @@ namespace Test {
     BOOST_CHECK(LineSurfaceStub(lineToCopy).constructedOk());
     // Copied and transformed ctor
     BOOST_CHECK(LineSurfaceStub(lineToCopy, transform).constructedOk());
+
+    /// Construct with nullptr bounds
+    Identifier          id;
+    DetectorElementStub detElem;
+    BOOST_CHECK_THROW(LineSurfaceStub nullBounds(nullptr, detElem, id),
+                      AssertionFailureException);
+
     BOOST_TEST_MESSAGE(
         "All LineSurface constructors are callable without problem");
   }
diff --git a/Tests/Surfaces/PlaneSurfaceTests.cpp b/Tests/Surfaces/PlaneSurfaceTests.cpp
index d8c28399410bc522ecb40294639e2cfbd89a0866..95ea58f7cd614c3eff1d97298397d6cb2f607a11 100644
--- a/Tests/Surfaces/PlaneSurfaceTests.cpp
+++ b/Tests/Surfaces/PlaneSurfaceTests.cpp
@@ -54,6 +54,12 @@ namespace Test {
     /// Copied and transformed
     PlaneSurface copiedTransformedPlaneSurface(PlaneSurfaceObject, *pTransform);
     BOOST_TEST(copiedTransformedPlaneSurface.type() == Surface::Plane);
+
+    /// Construct with nullptr bounds
+    Identifier          id;
+    DetectorElementStub detElem;
+    BOOST_CHECK_THROW(PlaneSurface nullBounds(nullptr, detElem, id),
+                      AssertionFailureException);
   }
   //
   /// Unit test for testing PlaneSurface properties