diff --git a/src/utils/checkpointing/ResumingData.cpp b/src/utils/checkpointing/ResumingData.cpp
index 561c3747defaed4d9e76da81ce695a25444628b3..2fc7996cc09f1d99d2ec827d5ea66ef2abe8b39a 100644
--- a/src/utils/checkpointing/ResumingData.cpp
+++ b/src/utils/checkpointing/ResumingData.cpp
@@ -154,9 +154,11 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
           m_id_to_iconnectivity_map.insert({id, Connectivity<3>::build(descriptor)});
           break;
         }
+          // LCOV_EXCL_START
         default: {
           throw UnexpectedError("invalid dimension " + std::to_string(dimension));
         }
+          // LCOV_EXCL_STOP
         }
       } else if (type == "dual_connectivity") {
         const DualMeshType type_of_dual     = connectivity_data.getAttribute("type_of_dual").read<DualMeshType>();
@@ -168,7 +170,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
         switch (iprimal_connectivity->dimension()) {
         case 1: {
           if (type_of_dual != DualMeshType::Dual1D) {
+            // LCOV_EXCL_START
             throw UnexpectedError("unexpected dual mesh type");
+            // LCOV_EXCL_STOP
           }
 
           const Connectivity<1>& primal_connectivity = dynamic_cast<const Connectivity<1>&>(*iprimal_connectivity);
@@ -186,7 +190,9 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
             m_id_to_iconnectivity_map.insert(
               {id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)});
           } else {
+            // LCOV_EXCL_START
             throw UnexpectedError("unexpected dual mesh type");
+            // LCOV_EXCL_STOP
           }
           break;
         }
@@ -200,16 +206,22 @@ ResumingData::_getConnectivityList(const HighFive::Group& checkpoint)
             m_id_to_iconnectivity_map.insert(
               {id, DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity)});
           } else {
+            // LCOV_EXCL_START
             throw UnexpectedError("unexpected dual mesh type");
+            // LCOV_EXCL_STOP
           }
           break;
         }
+          // LCOV_EXCL_START
         default: {
           throw UnexpectedError("unexpected dimension");
         }
+          // LCOV_EXCL_STOP
         }
       } else {
+        // LCOV_EXCL_START
         throw UnexpectedError("invalid connectivity type: " + type);
+        // LCOV_EXCL_STOP
       }
     }
   }
@@ -229,11 +241,15 @@ ResumingData::_readPolygonalMesh(const HighFive::Group& mesh_data)
   const uint64_t connectivity_id = mesh_data.getAttribute("connectivity").read<uint64_t>();
   auto i_id_to_iconnectivity     = m_id_to_iconnectivity_map.find(connectivity_id);
   if (i_id_to_iconnectivity == m_id_to_iconnectivity_map.end()) {
+    // LCOV_EXCL_START
     throw UnexpectedError("cannot find connectivity " + std::to_string(connectivity_id));
+    // LCOV_EXCL_STOP
   }
   std::shared_ptr<const IConnectivity> i_connectivity = i_id_to_iconnectivity->second;
   if (i_connectivity->dimension() != Dimension) {
+    // LCOV_EXCL_START
     throw UnexpectedError("invalid connectivity dimension " + std::to_string(i_connectivity->dimension()));
+    // LCOV_EXCL_STOP
   }
 
   std::shared_ptr<const Connectivity<Dimension>> connectivity =
@@ -288,9 +304,11 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
           m_id_to_mesh_variant_map.insert({id, this->_readPolygonalMesh<3>(mesh_data)});
           break;
         }
+          // LCOV_EXCL_START
         default: {
           throw UnexpectedError("invalid mesh dimension " + std::to_string(dimension));
         }
+          // LCOV_EXCL_STOP
         }
       } else if (type == "dual_mesh") {
         const DualMeshType type_of_dual = mesh_data.getAttribute("type_of_dual").read<DualMeshType>();
@@ -305,7 +323,9 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
               if (type_of_dual == DualMeshType::Dual1D) {
                 m_id_to_mesh_variant_map.insert({id, DualMeshManager::instance().getDual1DMesh(primal_mesh_variant)});
               } else {
+                // LCOV_EXCL_START
                 throw UnexpectedError("unexpected dual mesh type");
+                // LCOV_EXCL_STOP
               }
             } else if constexpr (std::is_same_v<MeshType, Mesh<2>> or std::is_same_v<MeshType, Mesh<3>>) {
               if (type_of_dual == DualMeshType::Diamond) {
@@ -315,14 +335,18 @@ ResumingData::_getMeshVariantList(const HighFive::Group& checkpoint)
                 m_id_to_mesh_variant_map.insert(
                   {id, DualMeshManager::instance().getMedianDualMesh(primal_mesh_variant)});
               } else {
+                // LCOV_EXCL_START
                 throw UnexpectedError("unexpected dual mesh type");
+                // LCOV_EXCL_STOP
               }
             }
           },
           primal_mesh_variant->variant());
 
       } else {
+        // LCOV_EXCL_START
         throw UnexpectedError("invalid mesh type");
+        // LCOV_EXCL_STOP
       }
     }
   }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6202c2ad4c3264b2e5f2e1819bd8e2ebc4225e81..d96587863d5ffc6f34a1a715e66b9098aa5db881 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -174,6 +174,7 @@ if(PUGS_HAS_HDF5)
     test_checkpointing_ItemType.cpp
     test_checkpointing_IWriter.cpp
     test_checkpointing_IZoneDescriptor.cpp
+    test_checkpointing_Mesh.cpp
     test_checkpointing_Table.cpp
   )
 endif(PUGS_HAS_HDF5)
diff --git a/tests/checkpointing_Mesh_utilities.hpp b/tests/checkpointing_Mesh_utilities.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..aabfacbbd6ca259de9468fda12ea706c8784005b
--- /dev/null
+++ b/tests/checkpointing_Mesh_utilities.hpp
@@ -0,0 +1,68 @@
+#ifndef CHECKPOINTING_MESH_UTILITIES_HPP
+#define CHECKPOINTING_MESH_UTILITIES_HPP
+
+#include <checkpointing_Connectivity_utilities.hpp>
+#include <mesh/Mesh.hpp>
+#include <mesh/MeshTraits.hpp>
+#include <mesh/MeshVariant.hpp>
+
+namespace test_only
+{
+
+PUGS_INLINE
+std::shared_ptr<const MeshVariant>
+duplicateMesh(std::shared_ptr<const MeshVariant> mesh_v)
+{
+  std::shared_ptr<const MeshVariant> new_mesh_v;
+
+  std::visit(
+    [&](auto&& mesh) {
+      using MeshType = mesh_type_t<decltype(mesh)>;
+      if constexpr (is_polygonal_mesh_v<MeshType>) {
+        using Rd = TinyVector<MeshType::Dimension>;
+        auto new_connectivity =
+          std::dynamic_pointer_cast<const typename MeshType::Connectivity>(duplicateConnectivity(mesh->connectivity()));
+
+        NodeValue<const Rd> new_xr{*new_connectivity, mesh->xr().arrayView()};
+        new_mesh_v = std::make_shared<MeshVariant>(std::make_shared<const MeshType>(new_connectivity, new_xr));
+      } else {
+        throw NotImplementedError("unexpected mesh type");
+      }
+    },
+    mesh_v->variant());
+
+  return new_mesh_v;
+}
+
+PUGS_INLINE bool
+isSameMesh(std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const MeshVariant> read_mesh_v)
+{
+  auto same_value = [](const auto& a, const auto& b) -> bool {
+    bool same = true;
+    for (size_t i = 0; i < a.size(); ++i) {
+      same &= (a[i] == b[i]);
+    }
+    return parallel::allReduceAnd(same);
+  };
+
+  bool same = true;
+
+  std::visit(
+    [&](auto&& mesh, auto&& read_mesh) {
+      using MeshType     = mesh_type_t<decltype(mesh)>;
+      using ReadMeshType = mesh_type_t<decltype(read_mesh)>;
+      if constexpr (std::is_same_v<MeshType, ReadMeshType>) {
+        same &= test_only::isSameConnectivity(mesh->connectivity(), read_mesh->connectivity());
+        same &= same_value(mesh->xr().arrayView(), read_mesh->xr().arrayView());
+      } else {
+        throw UnexpectedError("mesh of different kind");
+      }
+    },
+    mesh_v->variant(), read_mesh_v->variant());
+
+  return same;
+}
+
+}   // namespace test_only
+
+#endif   // CHECKPOINTING_MESH_UTILITIES_HPP
diff --git a/tests/test_checkpointing_Mesh.cpp b/tests/test_checkpointing_Mesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d9a27ea40585c1b7253881fd93d7a3ba3404b5e
--- /dev/null
+++ b/tests/test_checkpointing_Mesh.cpp
@@ -0,0 +1,159 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <utils/Messenger.hpp>
+
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/Mesh.hpp>
+#include <mesh/MeshVariant.hpp>
+#include <utils/GlobalVariableManager.hpp>
+#include <utils/checkpointing/ReadMesh.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+#include <utils/checkpointing/WriteMesh.hpp>
+
+#include <MeshDataBaseForTests.hpp>
+#include <checkpointing_Mesh_utilities.hpp>
+
+#include <filesystem>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("checkpointing_Mesh", "[utils/checkpointing]")
+{
+  std::string tmp_dirname;
+  {
+    {
+      if (parallel::rank() == 0) {
+        tmp_dirname = [&]() -> std::string {
+          std::string temp_filename = std::filesystem::temp_directory_path() / "pugs_checkpointing_XXXXXX";
+          return std::string{mkdtemp(&temp_filename[0])};
+        }();
+      }
+      parallel::broadcast(tmp_dirname, 0);
+    }
+    std::filesystem::path path = tmp_dirname;
+    const std::string filename = path / "checkpoint.h5";
+
+    HighFive::FileAccessProps fapl;
+    fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL});
+    fapl.add(HighFive::MPIOCollectiveMetadata{});
+    HighFive::File file = HighFive::File(filename, HighFive::File::Truncate, fapl);
+
+    const size_t initial_connectivity_id = GlobalVariableManager::instance().getConnectivityId();
+    const size_t initial_mesh_id         = GlobalVariableManager::instance().getMeshId();
+
+    SECTION("Mesh")
+    {
+      HighFive::Group checkpoint_group_0 = file.createGroup("checkpoint_0");
+      HighFive::Group symbol_table_0     = checkpoint_group_0.createGroup("symbol_table");
+
+      HighFive::Group checkpoint_group_1 = file.createGroup("checkpoint_1");
+      HighFive::Group symbol_table_1     = checkpoint_group_1.createGroup("symbol_table");
+
+      {   // Write
+        auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh();
+
+        // creates artificially holes in numbering
+        test_only::duplicateMesh(mesh_1d);
+
+        auto new_mesh_1d = test_only::duplicateMesh(mesh_1d);
+
+        using DataHandlerT = DataHandler<const MeshVariant>;
+
+        checkpointing::writeMesh("mesh_1d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_1d)}, file,
+                                 checkpoint_group_0, symbol_table_0);
+        checkpointing::writeMesh("mesh_1d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_1d)}, file,
+                                 checkpoint_group_1, symbol_table_1);
+
+        auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh();
+
+        // creates artificially holes in numbering
+        test_only::duplicateMesh(mesh_2d);
+        auto new_mesh_2d = test_only::duplicateMesh(mesh_2d);
+
+        checkpointing::writeMesh("mesh_2d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_2d)}, file,
+                                 checkpoint_group_0, symbol_table_0);
+        checkpointing::writeMesh("mesh_2d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_2d)}, file,
+                                 checkpoint_group_1, symbol_table_1);
+
+        HighFive::Group global_variables_group_0 = checkpoint_group_0.createGroup("singleton/global_variables");
+        global_variables_group_0.createAttribute("connectivity_id",
+                                                 GlobalVariableManager::instance().getConnectivityId());
+        global_variables_group_0.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId());
+
+        auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh();
+
+        // creates artificially holes in numbering
+        test_only::duplicateMesh(mesh_3d);
+
+        auto new_mesh_3d = test_only::duplicateMesh(mesh_3d);
+        checkpointing::writeMesh("mesh_3d", EmbeddedData{std::make_shared<DataHandlerT>(new_mesh_3d)}, file,
+                                 checkpoint_group_1, symbol_table_1);
+
+        // creates artificially holes in numbering
+        test_only::duplicateMesh(mesh_3d);
+        test_only::duplicateMesh(mesh_3d);
+        test_only::duplicateMesh(mesh_3d);
+
+        HighFive::Group global_variables_group_1 = checkpoint_group_1.createGroup("singleton/global_variables");
+        global_variables_group_1.createAttribute("connectivity_id",
+                                                 GlobalVariableManager::instance().getConnectivityId());
+        global_variables_group_1.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId());
+      }
+
+      // reset to reuse after resuming
+      GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+      GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+
+      file.flush();
+
+      checkpointing::ResumingData::create();
+      checkpointing::ResumingData::instance().readData(checkpoint_group_1, nullptr);
+
+      GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+      GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+      {   // Read
+
+        auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh();
+
+        EmbeddedData e_mesh_1d = checkpointing::readMesh("mesh_1d", symbol_table_1);
+
+        REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_1d.get()));
+
+        std::shared_ptr<const MeshVariant> read_mesh_1d =
+          dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_1d.get()).data_ptr();
+
+        REQUIRE(test_only::isSameMesh(mesh_1d, read_mesh_1d));
+
+        auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh();
+
+        EmbeddedData e_mesh_2d = checkpointing::readMesh("mesh_2d", symbol_table_1);
+
+        REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_2d.get()));
+
+        std::shared_ptr<const MeshVariant> read_mesh_2d =
+          dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_2d.get()).data_ptr();
+
+        REQUIRE(test_only::isSameMesh(mesh_2d, read_mesh_2d));
+
+        auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh();
+
+        EmbeddedData e_mesh_3d = checkpointing::readMesh("mesh_3d", symbol_table_1);
+
+        REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_3d.get()));
+
+        std::shared_ptr<const MeshVariant> read_mesh_3d =
+          dynamic_cast<const DataHandler<const MeshVariant>&>(e_mesh_3d.get()).data_ptr();
+
+        REQUIRE(test_only::isSameMesh(mesh_3d, read_mesh_3d));
+      }
+      checkpointing::ResumingData::destroy();
+    }
+  }
+
+  parallel::barrier();
+  if (parallel::rank() == 0) {
+    std::filesystem::remove_all(std::filesystem::path{tmp_dirname});
+  }
+}