diff --git a/dune/vtk/utility/CMakeLists.txt b/dune/vtk/utility/CMakeLists.txt
index efed088eecbd4209a6ed113647ea3500efe5b064..a611ab983b2140448d2b872e2084ba5ef99df37d 100644
--- a/dune/vtk/utility/CMakeLists.txt
+++ b/dune/vtk/utility/CMakeLists.txt
@@ -4,6 +4,7 @@ dune_add_library("filesystem" OBJECT
 #install headers
 install(FILES
   enum.hh
+  errors.hh
   filesystem.hh
   lagrangepoints.hh
   lagrangepoints.impl.hh
diff --git a/dune/vtk/utility/errors.hh b/dune/vtk/utility/errors.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d97fc8d12c18c4128ac60c23f4e80669c23ab31c
--- /dev/null
+++ b/dune/vtk/utility/errors.hh
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <dune/common/exceptions.hh>
+
+/**
+ * \file
+ * \brief Macro for wrapping error checks and throwing exceptions
+ */
+
+namespace Dune {
+
+class VtkError : public Exception {};
+
+}
+
+/**
+ * \brief check if condition \a cond holds; otherwise, throw a VtkError with a message.
+ */
+#define VTK_ASSERT_MSG(cond, text)      \
+  do {                                  \
+    if (!(cond))                        \
+      DUNE_THROW(Dune::VtkError, text); \
+  } while (false)
+
+
+/**
+ * \brief check if condition \a cond holds; otherwise, throw a VtkError.
+ */
+#define VTK_ASSERT(cond)                \
+  do {                                  \
+    if (!(cond))                        \
+      DUNE_THROW(Dune::VtkError, #cond); \
+  } while (false)
diff --git a/dune/vtk/vtkreader.impl.hh b/dune/vtk/vtkreader.impl.hh
index 308b33dd296cf03a407fed7ec512834213d0d580..e5507a50e4552f0d5c413a39738f89eacd8ba67e 100644
--- a/dune/vtk/vtkreader.impl.hh
+++ b/dune/vtk/vtkreader.impl.hh
@@ -10,6 +10,7 @@
 #include <dune/common/classname.hh>
 #include <dune/common/version.hh>
 
+#include "utility/errors.hh"
 #include "utility/filesystem.hh"
 #include "utility/string.hh"
 
@@ -23,7 +24,7 @@ void VtkReader<Grid,Creator>::read (std::string const& filename, bool fillCreato
     DUNE_THROW(IOError, "File " << filename << " does not exist!");
 
   std::ifstream input(filename, std::ios_base::in | std::ios_base::binary);
-  assert(input.is_open());
+  VTK_ASSERT(input.is_open());
 
   std::string ext = Vtk::Path(filename).extension().string();
   if (ext == ".vtu") {
@@ -32,7 +33,7 @@ void VtkReader<Grid,Creator>::read (std::string const& filename, bool fillCreato
   } else if (ext == ".pvtu") {
     readParallelFileFromStream(input, comm().rank(), comm().size(), fillCreator);
   } else {
-    DUNE_THROW(IOError, "File has unknown file-extension '" << ext << "'. Allowed are only '.vtu' and '.pvtu'.");
+    DUNE_THROW(Dune::VtkError, "File has unknown file-extension '" << ext << "'. Allowed are only '.vtu' and '.pvtu'.");
   }
 }
 
@@ -56,16 +57,16 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
       auto attr = parseXml(line, closed);
 
       if (!attr["type"].empty())
-        assert(attr["type"] == "UnstructuredGrid");
+        VTK_ASSERT_MSG(attr["type"] == "UnstructuredGrid", "VtkReader supports UnstructuredGrid types");
       if (!attr["version"].empty())
-        assert(std::stod(attr["version"]) == 1.0);
+        VTK_ASSERT_MSG(std::stod(attr["version"]) == 1.0, "File format must be 1.0");
       if (!attr["byte_order"].empty())
-        assert(attr["byte_order"] == "LittleEndian");
+        VTK_ASSERT_MSG(attr["byte_order"] == "LittleEndian", "LittleEndian byte order supported");
       if (!attr["header_type"].empty())
-        assert(attr["header_type"] == "UInt64");
+        VTK_ASSERT_MSG(attr["header_type"] == "UInt64", "Header integer type must be UInt64");
       if (!attr["compressor"].empty()) {
         compressor = attr["compressor"];
-        assert(compressor == "vtkZLibDataCompressor"); // only ZLib compression supported
+        VTK_ASSERT_MSG(compressor == "vtkZLibDataCompressor", "Only ZLib compression supported");
       }
       section = VTK_FILE;
     }
@@ -79,7 +80,8 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
       bool closed = false;
       auto attr = parseXml(line, closed);
 
-      assert(attr.count("NumberOfPoints") > 0 && attr.count("NumberOfCells") > 0);
+      VTK_ASSERT_MSG(attr.count("NumberOfPoints") > 0 && attr.count("NumberOfCells") > 0,
+        "Number of points or cells in file must be > 0");
       numberOfPoints_ = std::stoul(attr["NumberOfPoints"]);
       numberOfCells_ = std::stoul(attr["NumberOfCells"]);
       section = PIECE;
@@ -129,7 +131,7 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
       data_offset = 0;
       if (!attr["offset"].empty()) {
         data_offset = std::stoul(attr["offset"]);
-        assert(data_format == "appended");
+        VTK_ASSERT_MSG(data_format == "appended", "Attribute 'offset' only supported by appended mode");
       }
 
       // Store attributes of DataArray
@@ -156,7 +158,7 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
       else if (section == CELLS)
         section = CELLS_DATA_ARRAY;
       else
-        DUNE_THROW(Exception, "Wrong section for <DataArray>");
+        DUNE_THROW(Dune::VtkError, "Wrong section for <DataArray>");
     }
     else if (line.substr(1,10) == "/DataArray") {
       if (section == PD_DATA_ARRAY)
@@ -168,13 +170,13 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
       else if (section == CELLS_DATA_ARRAY)
         section = CELLS;
       else
-        DUNE_THROW(Exception, "Wrong section for </DataArray>");
+        DUNE_THROW(Dune::VtkError, "Wrong section for </DataArray>");
     }
     else if (isSection(line, "AppendedData", section, VTK_FILE)) {
       bool closed = false;
       auto attr = parseXml(line, closed);
       if (!attr["encoding"].empty())
-        assert(attr["encoding"] == "raw"); // base64 encoding not supported
+        VTK_ASSERT_MSG(attr["encoding"] == "raw", "base64 encoding not supported");
 
       offset0_ = findAppendedDataPosition(input);
       if (dataArray_["points"].type == Vtk::FLOAT32)
@@ -223,7 +225,7 @@ void VtkReader<Grid,Creator>::readSerialFileFromStream (std::ifstream& input, bo
   }
 
   if (section != NO_SECTION)
-    DUNE_THROW(IOError, "VTK-File is incomplete. It must end with </VTKFile>!");
+    DUNE_THROW(Dune::VtkError, "VTK-File is incomplete. It must end with </VTKFile>!");
 
   if (fillCreator)
     fillGridCreator();
@@ -244,15 +246,15 @@ void VtkReader<Grid,Creator>::readParallelFileFromStream (std::ifstream& input,
       auto attr = parseXml(line, closed);
 
       if (!attr["type"].empty())
-        assert(attr["type"] == "PUnstructuredGrid");
+        VTK_ASSERT_MSG(attr["type"] == "PUnstructuredGrid", "VtkReader supports PUnstructuredGrid types");
       if (!attr["version"].empty())
-        assert(std::stod(attr["version"]) == 1.0);
+        VTK_ASSERT_MSG(std::stod(attr["version"]) == 1.0, "File format must be 1.0");
       if (!attr["byte_order"].empty())
-        assert(attr["byte_order"] == "LittleEndian");
+        VTK_ASSERT_MSG(attr["byte_order"] == "LittleEndian", "LittleEndian byte order supported");
       if (!attr["header_type"].empty())
-        assert(attr["header_type"] == "UInt64");
+        VTK_ASSERT_MSG(attr["header_type"] == "UInt64", "Header integer type must be UInt64");
       if (!attr["compressor"].empty())
-        assert(attr["compressor"] == "vtkZLibDataCompressor"); // only ZLib compression supported
+        VTK_ASSERT_MSG(attr["compressor"] == "vtkZLibDataCompressor", "Only ZLib compression supported");
       section = VTK_FILE;
     }
     else if (isSection(line, "/VTKFile", section, VTK_FILE))
@@ -265,7 +267,7 @@ void VtkReader<Grid,Creator>::readParallelFileFromStream (std::ifstream& input,
       bool closed = false;
       auto attr = parseXml(line, closed);
 
-      assert(attr.count("Source") > 0);
+      VTK_ASSERT_MSG(attr.count("Source") > 0, "No source files for partitions provided");
       pieces_.push_back(attr["Source"]);
     }
 
@@ -274,7 +276,7 @@ void VtkReader<Grid,Creator>::readParallelFileFromStream (std::ifstream& input,
   }
 
   if (section != NO_SECTION)
-    DUNE_THROW(IOError, "VTK-File is incomplete. It must end with </VTKFile>!");
+    DUNE_THROW(Dune::VtkError, "VTK-File is incomplete. It must end with </VTKFile>!");
 
   if (fillCreator)
     fillGridCreator();
@@ -333,8 +335,8 @@ typename VtkReader<Grid,Creator>::Sections
 VtkReader<Grid,Creator>::readPoints (std::ifstream& input, std::string name)
 {
   using T = typename GlobalCoordinate::value_type;
-  assert(numberOfPoints_ > 0);
-  assert(dataArray_["points"].components == 3u);
+  VTK_ASSERT(numberOfPoints_ > 0);
+  VTK_ASSERT(dataArray_["points"].components == 3u);
 
   Sections sec;
 
@@ -342,8 +344,8 @@ VtkReader<Grid,Creator>::readPoints (std::ifstream& input, std::string name)
   sec = readDataArray(input, point_values, 3*numberOfPoints_, POINTS_DATA_ARRAY, POINTS);
   if (sec != POINTS)
     sec = skipRestOfDataArray(input, POINTS_DATA_ARRAY, POINTS);
-  assert(sec == POINTS);
-  assert(point_values.size() == 3*numberOfPoints_);
+  VTK_ASSERT(sec == POINTS);
+  VTK_ASSERT(point_values.size() == 3*numberOfPoints_);
 
   // extract points from continuous values
   GlobalCoordinate p;
@@ -364,11 +366,11 @@ template <class Grid, class Creator>
   template <class T>
 void VtkReader<Grid,Creator>::readPointsAppended (std::ifstream& input)
 {
-  assert(numberOfPoints_ > 0);
-  assert(dataArray_["points"].components == 3u);
+  VTK_ASSERT(numberOfPoints_ > 0);
+  VTK_ASSERT(dataArray_["points"].components == 3u);
   std::vector<T> point_values;
   readAppended(input, point_values, dataArray_["points"].offset);
-  assert(point_values.size() == 3*numberOfPoints_);
+  VTK_ASSERT(point_values.size() == 3*numberOfPoints_);
 
   // extract points from continuous values
   GlobalCoordinate p;
@@ -389,18 +391,18 @@ VtkReader<Grid,Creator>::readCells (std::ifstream& input, std::string name)
 {
   Sections sec = CELLS_DATA_ARRAY;
 
-  assert(numberOfCells_ > 0);
+  VTK_ASSERT(numberOfCells_ > 0);
   if (name == "types") {
     sec = readDataArray(input, vec_types, numberOfCells_, CELLS_DATA_ARRAY, CELLS);
-    assert(vec_types.size() == numberOfCells_);
+    VTK_ASSERT(vec_types.size() == numberOfCells_);
   } else if (name == "offsets") {
     sec = readDataArray(input, vec_offsets, numberOfCells_, CELLS_DATA_ARRAY, CELLS);
-    assert(vec_offsets.size() == numberOfCells_);
+    VTK_ASSERT(vec_offsets.size() == numberOfCells_);
   } else if (name == "connectivity") {
     sec = readDataArray(input, vec_connectivity, std::size_t(-1), CELLS_DATA_ARRAY, CELLS);
   } else if (name == "global_point_ids") {
     sec = readDataArray(input, vec_point_ids, numberOfPoints_, CELLS_DATA_ARRAY, CELLS);
-    assert(vec_point_ids.size() == numberOfPoints_);
+    VTK_ASSERT(vec_point_ids.size() == numberOfPoints_);
   }
 
   return sec;
@@ -410,14 +412,14 @@ VtkReader<Grid,Creator>::readCells (std::ifstream& input, std::string name)
 template <class Grid, class Creator>
 void VtkReader<Grid,Creator>::readCellsAppended (std::ifstream& input)
 {
-  assert(numberOfCells_ > 0);
+  VTK_ASSERT(numberOfCells_ > 0);
   auto types_data = dataArray_["types"];
   auto offsets_data = dataArray_["offsets"];
   auto connectivity_data = dataArray_["connectivity"];
 
-  assert(types_data.type == Vtk::UINT8);
+  VTK_ASSERT(types_data.type == Vtk::UINT8);
   readAppended(input, vec_types, types_data.offset);
-  assert(vec_types.size() == numberOfCells_);
+  VTK_ASSERT(vec_types.size() == numberOfCells_);
 
   if (offsets_data.type == Vtk::INT64)
     readAppended(input, vec_offsets, offsets_data.offset);
@@ -428,7 +430,7 @@ void VtkReader<Grid,Creator>::readCellsAppended (std::ifstream& input)
     std::copy(offsets.begin(), offsets.end(), vec_offsets.begin());
   }
   else { DUNE_THROW(Dune::NotImplemented, "Unsupported DataType in Cell offsets."); }
-  assert(vec_offsets.size() == numberOfCells_);
+  VTK_ASSERT(vec_offsets.size() == numberOfCells_);
 
   if (connectivity_data.type == Vtk::INT64)
     readAppended(input, vec_connectivity, connectivity_data.offset);
@@ -439,13 +441,13 @@ void VtkReader<Grid,Creator>::readCellsAppended (std::ifstream& input)
     std::copy(connectivity.begin(), connectivity.end(), vec_connectivity.begin());
   }
   else { DUNE_THROW(Dune::NotImplemented, "Unsupported DataType in Cell connectivity."); }
-  assert(vec_connectivity.size() == std::size_t(vec_offsets.back()));
+  VTK_ASSERT(vec_connectivity.size() == std::size_t(vec_offsets.back()));
 
   if (dataArray_.count("global_point_ids") > 0) {
     auto point_id_data = dataArray_["global_point_ids"];
-    assert(point_id_data.type == Vtk::UINT64);
+    VTK_ASSERT(point_id_data.type == Vtk::UINT64);
     readAppended(input, vec_point_ids, point_id_data.offset);
-    assert(vec_point_ids.size() == numberOfPoints_);
+    VTK_ASSERT(vec_point_ids.size() == numberOfPoints_);
   }
 }
 
@@ -470,13 +472,13 @@ void read_compressed (T* buffer, unsigned char* buffer_in,
   Bytef* uncompressed_buffer = reinterpret_cast<Bytef*>(buffer);
 
   input.read((char*)(compressed_buffer), compressed_space);
-  assert(uLongf(input.gcount()) == compressed_space);
+  VTK_ASSERT(uLongf(input.gcount()) == compressed_space);
 
   if (uncompress(uncompressed_buffer, &uncompressed_space, compressed_buffer, compressed_space) != Z_OK) {
     std::cerr << "Zlib error while uncompressing data.\n";
     std::abort();
   }
-  assert(uLongf(bs) == uncompressed_space);
+  VTK_ASSERT(uLongf(bs) == uncompressed_space);
 #else
   std::cerr << "Can not call read_compressed without compression enabled!\n";
   std::abort();
@@ -504,7 +506,7 @@ void VtkReader<Grid,Creator>::readAppended (std::ifstream& input, std::vector<T>
     input.read((char*)&block_size, sizeof(std::uint64_t));
     input.read((char*)&last_block_size, sizeof(std::uint64_t));
 
-    assert(block_size % sizeof(T) == 0);
+    VTK_ASSERT(block_size % sizeof(T) == 0);
 
     // total size of the uncompressed data
     size = block_size * (num_blocks-1) + last_block_size;
@@ -515,7 +517,7 @@ void VtkReader<Grid,Creator>::readAppended (std::ifstream& input, std::vector<T>
   } else {
     input.read((char*)&size, sizeof(std::uint64_t));
   }
-  assert(size > 0 && (size % sizeof(T)) == 0);
+  VTK_ASSERT(size > 0 && (size % sizeof(T)) == 0);
   values.resize(size / sizeof(T));
 
   if (format_ == Vtk::COMPRESSED) {
@@ -531,7 +533,7 @@ void VtkReader<Grid,Creator>::readAppended (std::ifstream& input, std::vector<T>
     }
   } else {
     input.read((char*)(values.data()), size);
-    assert(input.gcount() == std::streamsize(size));
+    VTK_ASSERT(input.gcount() == std::streamsize(size));
   }
 }
 
@@ -539,9 +541,9 @@ void VtkReader<Grid,Creator>::readAppended (std::ifstream& input, std::vector<T>
 template <class Grid, class Creator>
 void VtkReader<Grid,Creator>::fillGridCreator (bool insertPieces)
 {
-  assert(vec_points.size() == numberOfPoints_);
-  assert(vec_types.size() == numberOfCells_);
-  assert(vec_offsets.size() == numberOfCells_);
+  VTK_ASSERT(vec_points.size() == numberOfPoints_);
+  VTK_ASSERT(vec_types.size() == numberOfCells_);
+  VTK_ASSERT(vec_offsets.size() == numberOfCells_);
 
   if (!vec_points.empty())
     creator_->insertVertices(vec_points, vec_point_ids);
@@ -597,7 +599,7 @@ std::map<std::string, std::string> VtkReader<Grid,Creator>::parseXml (std::strin
     case XML_NAME_ASSIGN:
       value.clear();
       escape = false;
-      assert( c == '"' && "Format error!" );
+      VTK_ASSERT_MSG( c == '"', "Format error!" );
       sec = XML_VALUE;
       break;
     case XML_VALUE:
@@ -612,7 +614,7 @@ std::map<std::string, std::string> VtkReader<Grid,Creator>::parseXml (std::strin
       }
       break;
     default:
-      assert(false && "Format error!");
+      VTK_ASSERT_MSG(false, "Format error!");
     }
   }