diff --git a/grudge/execution.py b/grudge/execution.py
index dba0648d820581f0f47febc308370cfea93e4d97..3cd9aade269db123d3ce2f91bebe3ccc7f6ba321 100644
--- a/grudge/execution.py
+++ b/grudge/execution.py
@@ -501,9 +501,6 @@ class ExecutionMapper(mappers.Evaluator,
             for in_grp, out_grp in zip(in_discr.groups, out_discr.groups):
                 assert in_grp.nelements == out_grp.nelements
 
-                if in_grp.nelements == 0:
-                    continue
-
                 # Cache operator
                 cache_key = "diff_batch", in_grp, out_grp, tuple(insn.operators),\
                     field.entry_dtype
diff --git a/test/test_grudge.py b/test/test_grudge.py
index 3318a84ddfaf6f2a477b8904ffdd16196f9b1bea..cd2b057d90d967ea53b348100e341a7a70b81c2d 100644
--- a/test/test_grudge.py
+++ b/test/test_grudge.py
@@ -1109,6 +1109,24 @@ def test_map_if(actx_factory):
     bind(discr, sym_if)(actx)
 
 
+def test_empty_boundary(actx_factory):
+    # https://github.com/inducer/grudge/issues/54
+
+    actx = actx_factory()
+
+    dim = 2
+    mesh = mgen.generate_regular_rect_mesh(
+            a=(-0.5,)*dim, b=(0.5,)*dim,
+            n=(8,)*dim, order=4)
+    discr = DGDiscretizationWithBoundaries(actx, mesh, order=4)
+    normal = bind(discr,
+            sym.normal(sym.BTAG_NONE, dim, dim=dim - 1))(actx)
+    from meshmode.dof_array import DOFArray
+    for component in normal:
+        assert isinstance(component, DOFArray)
+        assert len(component) == len(discr.discr_from_dd(sym.BTAG_NONE).groups)
+
+
 # You can test individual routines by typing
 # $ python test_grudge.py 'test_routine()'