diff --git a/src/mesh/Connectivity.cpp b/src/mesh/Connectivity.cpp
index 7b81eeb0326e7cd5bc5df2b9c6d45b642dcb5e56..005dc1f6556af1fe0a4b5d72f6507890955c865b 100644
--- a/src/mesh/Connectivity.cpp
+++ b/src/mesh/Connectivity.cpp
@@ -95,6 +95,24 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
     m_edge_number   = WeakEdgeValue<int>(*this, node_number_array);
     m_edge_owner    = WeakEdgeValue<int>(*this, node_owner_array);
     m_edge_is_owned = WeakEdgeValue<bool>(*this, node_is_owned_array);
+
+    // edge and face references are set equal to node references
+    m_ref_edge_list_vector.reserve(descriptor.template refItemListVector<ItemType::node>().size());
+    m_ref_face_list_vector.reserve(descriptor.template refItemListVector<ItemType::node>().size());
+    for (auto ref_node_list : descriptor.template refItemListVector<ItemType::node>()) {
+      const RefId ref_id            = ref_node_list.refId();
+      Array<const NodeId> node_list = ref_node_list.list();
+      Array<EdgeId> edge_list(node_list.size());
+      Array<FaceId> face_list(node_list.size());
+      for (size_t i = 0; i < node_list.size(); ++i) {
+        edge_list[i] = EdgeId::base_type{node_list[i]};
+        face_list[i] = FaceId::base_type{node_list[i]};
+      }
+
+      m_ref_edge_list_vector.emplace_back(RefItemList<ItemType::edge>(ref_id, edge_list));
+      m_ref_face_list_vector.emplace_back(RefItemList<ItemType::face>(ref_id, face_list));
+    }
+
   } else {
     m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.face_to_node_vector;
 
@@ -134,6 +152,19 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
       m_edge_owner    = WeakEdgeValue<int>(*this, face_owner_array);
       m_edge_is_owned = WeakEdgeValue<bool>(*this, face_is_owned_array);
 
+      // edge references are set equal to face references
+      m_ref_edge_list_vector.reserve(descriptor.template refItemListVector<ItemType::face>().size());
+      for (auto ref_face_list : descriptor.template refItemListVector<ItemType::face>()) {
+        const RefId ref_id            = ref_face_list.refId();
+        Array<const FaceId> face_list = ref_face_list.list();
+        Array<EdgeId> edge_list(face_list.size());
+        for (size_t i = 0; i < face_list.size(); ++i) {
+          edge_list[i] = EdgeId::base_type{face_list[i]};
+        }
+
+        m_ref_edge_list_vector.emplace_back(RefItemList<ItemType::edge>(ref_id, edge_list));
+      }
+
     } else {
       m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edge_to_node_vector;
 
diff --git a/src/mesh/MeshFaceBoundary.cpp b/src/mesh/MeshFaceBoundary.cpp
index 751bcf962ca9ce2b8f7e7e5eab240a1c4768bcfb..4e718f25197d3b387c2772b460f122227016f1cf 100644
--- a/src/mesh/MeshFaceBoundary.cpp
+++ b/src/mesh/MeshFaceBoundary.cpp
@@ -9,6 +9,7 @@ MeshFaceBoundary<Dimension>::MeshFaceBoundary(const Mesh<Connectivity<Dimension>
   : m_face_list(ref_face_list.list()), m_boundary_name(ref_face_list.refId().tagName())
 {}
 
+template MeshFaceBoundary<1>::MeshFaceBoundary(const Mesh<Connectivity<1>>&, const RefFaceList&);
 template MeshFaceBoundary<2>::MeshFaceBoundary(const Mesh<Connectivity<2>>&, const RefFaceList&);
 template MeshFaceBoundary<3>::MeshFaceBoundary(const Mesh<Connectivity<3>>&, const RefFaceList&);
 
@@ -21,14 +22,32 @@ getMeshFaceBoundary(const Mesh<Connectivity<Dimension>>& mesh, const IBoundaryDe
     const auto& ref_face_list = mesh.connectivity().template refItemList<ItemType::face>(i_ref_face_list);
     const RefId& ref          = ref_face_list.refId();
     if (ref == boundary_descriptor) {
+      auto face_list           = ref_face_list.list();
+      auto face_to_cell_matrix = mesh.connectivity().faceToCellMatrix();
+
+      bool is_bad = false;
+      parallel_for(face_list.size(), [=, &is_bad](int l) {
+        const auto& face_cells = face_to_cell_matrix[face_list[l]];
+        if (face_cells.size() > 1) {
+          is_bad = true;
+        }
+      });
+
+      if (parallel::allReduceOr(is_bad)) {
+        std::ostringstream ost;
+        ost << "invalid boundary " << rang::fgB::yellow << boundary_descriptor << rang::style::reset
+            << ": inner faces cannot be used to define mesh boundaries";
+        throw NormalError(ost.str());
+      }
+
       return MeshFaceBoundary<Dimension>{mesh, ref_face_list};
     }
   }
 
   std::ostringstream ost;
-  ost << "cannot find surface with name " << rang::fgB::red << boundary_descriptor << rang::style::reset << '\n';
+  ost << "cannot find face list with name " << rang::fgB::red << boundary_descriptor << rang::style::reset << '\n';
   ost << "The mesh contains " << mesh.connectivity().template numberOfRefItemList<ItemType::face>()
-      << " face boundaries: ";
+      << " referenced face lists: ";
   for (size_t i_ref_face_list = 0; i_ref_face_list < mesh.connectivity().template numberOfRefItemList<ItemType::face>();
        ++i_ref_face_list) {
     const auto& ref_face_list = mesh.connectivity().template refItemList<ItemType::face>(i_ref_face_list);
diff --git a/tests/test_MeshFaceBoundary.cpp b/tests/test_MeshFaceBoundary.cpp
index 5b390e17f6b56001cb9abd119eeb8486a97b6dff..3ab99dcd35d2b90dfc632810504574a6cc95b4b1 100644
--- a/tests/test_MeshFaceBoundary.cpp
+++ b/tests/test_MeshFaceBoundary.cpp
@@ -15,12 +15,34 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 {
   auto is_same = [](const auto& a, const auto& b) -> bool {
     if (a.size() > 0 and b.size() > 0) {
-      return (a[0] == b[0]);
+      return (a.size() == b.size()) and (&(a[0]) == &(b[0]));
     } else {
       return (a.size() == b.size());
     }
   };
 
+  auto get_face_list_from_tag = [](const size_t tag, const auto& connectivity) -> Array<const FaceId> {
+    for (size_t i = 0; i < connectivity.template numberOfRefItemList<ItemType::face>(); ++i) {
+      const auto& ref_face_list = connectivity.template refItemList<ItemType::face>(i);
+      const RefId ref_id        = ref_face_list.refId();
+      if (ref_id.tagNumber() == tag) {
+        return ref_face_list.list();
+      }
+    }
+    return {};
+  };
+
+  auto get_face_list_from_name = [](const std::string& name, const auto& connectivity) -> Array<const FaceId> {
+    for (size_t i = 0; i < connectivity.template numberOfRefItemList<ItemType::face>(); ++i) {
+      const auto& ref_face_list = connectivity.template refItemList<ItemType::face>(i);
+      const RefId ref_id        = ref_face_list.refId();
+      if (ref_id.tagName() == name) {
+        return ref_face_list.list();
+      }
+    }
+    return {};
+  };
+
   SECTION("1D")
   {
     static constexpr size_t Dimension = 1;
@@ -35,20 +57,28 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {0, 1};
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
           const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+      {
+        const std::set<std::string> name_set = {"XMIN", "XMAX"};
+
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor named_boundary_descriptor(name);
           const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -60,20 +90,27 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {1, 2};
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
           const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
+
+      {
+        const std::set<std::string> name_set = {"XMIN", "XMAX"};
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor named_boundary_descriptor(name);
           const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -93,20 +130,27 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {0, 1, 2, 3};
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
           const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
-          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+      {
+        const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX"};
+
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor numbered_boundary_descriptor(name);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -118,20 +162,27 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {1, 2, 3, 4};
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
           const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
-          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+      {
+        const std::set<std::string> name_set = {"XMIN", "YMIN", "XMAX", "YMIN"};
+
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor numbered_boundary_descriptor(name);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -151,21 +202,27 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {0, 1, 2, 3, 4, 5};
+
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
-          // force copy for tests
-          auto face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
-          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+      {
+        const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"};
+
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor numbered_boundary_descriptor(name);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -177,21 +234,27 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
 
       const ConnectivityType& connectivity = mesh.connectivity();
 
-      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
-        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
-        const RefId ref_id        = ref_face_list.refId();
+      {
+        const std::set<size_t> tag_set = {22, 23, 24, 25, 26, 27};
 
-        {
-          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
-          // force copy for tests
-          auto face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        for (auto tag : tag_set) {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+
+          auto face_list = get_face_list_from_tag(tag, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
+      }
 
-        {
-          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
-          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
-          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+      {
+        const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"};
+
+        for (auto name : name_set) {
+          NamedBoundaryDescriptor numbered_boundary_descriptor(name);
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+
+          auto face_list = get_face_list_from_name(name, connectivity);
+          REQUIRE(is_same(face_boundary.faceList(), face_list));
         }
       }
     }
@@ -212,9 +275,63 @@ TEST_CASE("MeshFaceBoundary", "[mesh]")
       NamedBoundaryDescriptor named_boundary_descriptor("invalid_boundary");
 
       REQUIRE_THROWS_WITH(getMeshFaceBoundary(mesh, named_boundary_descriptor),
-                          "error: cannot find surface with name \"invalid_boundary\"\nThe mesh contains 8 face "
-                          "boundaries: XMIN(22), XMAX(23), ZMAX(24), ZMIN(25), YMAX(26), YMIN(27), INTERFACE1(55), "
+                          "error: cannot find face list with name \"invalid_boundary\"\nThe mesh contains 8 referenced "
+                          "face lists: XMIN(22), XMAX(23), ZMAX(24), ZMIN(25), YMAX(26), YMIN(27), INTERFACE1(55), "
                           "INTERFACE2(56)");
     }
+
+    SECTION("surface is inside")
+    {
+      SECTION("1D")
+      {
+        static constexpr size_t Dimension = 1;
+
+        using ConnectivityType = Connectivity<Dimension>;
+        using MeshType         = Mesh<ConnectivityType>;
+
+        std::shared_ptr p_mesh = MeshDataBaseForTests::get().unordered1DMesh();
+        const MeshType& mesh   = *p_mesh;
+
+        NamedBoundaryDescriptor named_boundary_descriptor("INTERFACE");
+
+        REQUIRE_THROWS_WITH(getMeshFaceBoundary(mesh, named_boundary_descriptor),
+                            "error: invalid boundary \"INTERFACE\": inner faces cannot be used to define mesh "
+                            "boundaries");
+      }
+
+      SECTION("2D")
+      {
+        static constexpr size_t Dimension = 2;
+
+        using ConnectivityType = Connectivity<Dimension>;
+        using MeshType         = Mesh<ConnectivityType>;
+
+        std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid2DMesh();
+        const MeshType& mesh   = *p_mesh;
+
+        NamedBoundaryDescriptor named_boundary_descriptor("INTERFACE");
+
+        REQUIRE_THROWS_WITH(getMeshFaceBoundary(mesh, named_boundary_descriptor),
+                            "error: invalid boundary \"INTERFACE\": inner faces cannot be used to define mesh "
+                            "boundaries");
+      }
+
+      SECTION("3D")
+      {
+        static constexpr size_t Dimension = 3;
+
+        using ConnectivityType = Connectivity<Dimension>;
+        using MeshType         = Mesh<ConnectivityType>;
+
+        std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
+        const MeshType& mesh   = *p_mesh;
+
+        NamedBoundaryDescriptor named_boundary_descriptor("INTERFACE1");
+
+        REQUIRE_THROWS_WITH(getMeshFaceBoundary(mesh, named_boundary_descriptor),
+                            "error: invalid boundary \"INTERFACE1\": inner faces cannot be used to define mesh "
+                            "boundaries");
+      }
+    }
   }
 }