diff --git a/model_server/rois/roiset.py b/model_server/rois/roiset.py
index 5933fbd5550afa8f570ed2a6e08704437effa8ba..996d6abb73cf7dc1342323103767048268f527f7 100644
--- a/model_server/rois/roiset.py
+++ b/model_server/rois/roiset.py
@@ -550,6 +550,8 @@ class RoiSet(object):
         return PatchStack(list(se_ext))
 
     def get_patch_obmap_acc(self, **kwargs) -> Union[PatchStack, None]:
+        if self.count == 0:
+            return None
         labels = self.df().index.sort_values().to_list()
         acc_masks = self.get_patch_masks_acc(**kwargs)
         return PatchStack([(acc_masks.iat(i).data > 0) * labels[i] for i in range(0, len(labels))])
@@ -908,13 +910,15 @@ class RoiSet(object):
         :param extractor: function that takes an RoiSet object and returns a DataFrame of features
         :param kwargs: variable-length keyword arguments that are passed to feature extractor
         """
+        if self.count == 0:
+            return
         df_features = extractor(self, **kwargs)
         insert_level(df_features, 'features')
         self._df = self._df.join(df_features)
 
 
     def get_features(self) -> pd.DataFrame:
-        return self.df().features
+        return self.df().get('features')
 
 
     @classmethod
diff --git a/tests/rois/test_features.py b/tests/rois/test_features.py
index 9afe81db3680fa82483f5341454ae52454567455..dceb59f5533920d8e9e101aaaa961b1d8b483356 100644
--- a/tests/rois/test_features.py
+++ b/tests/rois/test_features.py
@@ -70,3 +70,23 @@ class TestRoiSetMonoProducts(unittest.TestCase):
         roiset.extract_features(regionprops, make_3d=True, channel=2)
         self.assertTrue(('features', 'intensity_std-2') in roiset.df().columns)
         self.assertTrue('intensity_std-2' in roiset.get_features())
+
+    def test_empty_roiset_extract_features(self):
+        import numpy as np
+        from model_server.base.accessors import InMemoryDataAccessor
+
+        arr_mask = InMemoryDataAccessor(np.zeros([*stack.hw, 1, stack.nz], dtype='uint8'))
+
+        roiset = RoiSet.from_binary_mask(
+            stack,
+            arr_mask,
+            params=RoiSetMetaParams(
+                filters={'area': {'min': 1e3, 'max': 1e4}},
+                expand_box_by=(128, 2)
+            ),
+            allow_3d=True,
+        )
+        self.assertEqual(roiset.count, 0)
+        roiset.extract_features(regionprops, make_3d=True, channel=2)
+        self.assertTrue(('features', 'intensity_std-2') not in roiset.df().columns)
+        self.assertIsNone(roiset.get_features())
\ No newline at end of file
diff --git a/tests/rois/test_roiset.py b/tests/rois/test_roiset.py
index 135d4446e4a84ede374d9740c71f444a24c63da5..fa6654e0e29e1a9e2b46e2799983fc8e2a4595f0 100644
--- a/tests/rois/test_roiset.py
+++ b/tests/rois/test_roiset.py
@@ -915,6 +915,12 @@ class TestEmptyRoiSet(unittest.TestCase):
         self.assertEqual(len(df_patches), 0)
         self.assertIsNone(roiset.get_patches_acc(make_3d=True))
 
+    def test_get_obmaps(self):
+        roiset = self.empty_roiset
+        self.assertEqual(roiset.count, 0)
+        acc_obmap = roiset.get_patch_obmap_acc(make_3d=True)
+        self.assertIsNone(acc_obmap)
+
     def test_run_exports(self):
         roiset = self.empty_roiset
         export_params = RoiSetExportParams(**{