diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
index 0d6bc1212dc1e175901f22276f0c98146791d5f6..27f0333bee4e2b2ffd9230a3fab14c47e0369242 100644
--- a/src/core/ext/filters/http/message_compress/message_compress_filter.cc
+++ b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
@@ -321,6 +321,11 @@ static grpc_error* pull_slice_from_send_message(call_data* calld) {
 // eventually result in calling on_send_message_next_done().
 static void continue_reading_send_message(grpc_call_element* elem) {
   call_data* calld = static_cast<call_data*>(elem->call_data);
+  if (calld->slices.length ==
+      calld->send_message_batch->payload->send_message.send_message->length()) {
+    finish_send_message(elem);
+    return;
+  }
   while (calld->send_message_batch->payload->send_message.send_message->Next(
       ~static_cast<size_t>(0), &calld->on_send_message_next_done)) {
     grpc_error* error = pull_slice_from_send_message(calld);
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
index 5ffa63bad1a99d0dbd3b63b5170746cf4c9a7286..6988ab843b2c1c7657d1f8166954112c18e3f9b2 100644
--- a/src/core/lib/transport/byte_stream.h
+++ b/src/core/lib/transport/byte_stream.h
@@ -40,7 +40,8 @@ class ByteStream : public Orphanable {
   // Returns true if the bytes are available immediately (in which case
   // on_complete will not be called), or false if the bytes will be available
   // asynchronously (in which case on_complete will be called when they
-  // are available).
+  // are available). Should not be called if there is no data left on the
+  // stream.
   //
   // max_size_hint can be set as a hint as to the maximum number
   // of bytes that would be acceptable to read.
diff --git a/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs
index 4ee7a8d9e79978d16e0e1c9580d10fabc1f7611e..7638747831243425d2da9dee071fd375aea39f09 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs
@@ -33,21 +33,6 @@ namespace Grpc.Core.Internal.Tests
             {
                 sliceBuffer.Complete();
                 CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray());
-                Assert.AreEqual(1, sliceBuffer.TestOnly_GetSliceCount());
-            }
-        }
-
-        [TestCase]
-        public void SliceBuffer_CompleteWithEmptyPayload()
-        {
-            using (var sliceBuffer = SliceBufferSafeHandle.Create())
-            {
-                var destSpan = sliceBuffer.GetSpan(0);
-                Assert.IsTrue(destSpan.Length > 0);  // some non-zero size memory is made available
-                sliceBuffer.Advance(0);
-                sliceBuffer.Complete();
-                CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray());
-                Assert.AreEqual(1, sliceBuffer.TestOnly_GetSliceCount());
             }
         }
 
diff --git a/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs b/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs
index e5b714f856f2fcca0c0e368a23725ef50be1bd3c..9cbdce1cfe37fdf8bdf20f80d9c89924876beb8d 100644
--- a/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs
@@ -130,12 +130,6 @@ namespace Grpc.Core.Internal
             return result;
         }
 
-        // for testing only
-        public int TestOnly_GetSliceCount()
-        {
-            return (int) Native.grpcsharp_slice_buffer_slice_count(this).ToUInt64();
-        }
-
         private void EnsureBufferSpace(int sizeHint)
         {
             GrpcPreconditions.CheckArgument(sizeHint >= 0);
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index b45880095573c504329f43cb992befd3c0ead3e6..d9bf85e02c7c404752190dc3009056d17b1134ad 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -1244,11 +1244,7 @@ GPR_EXPORT void* GPR_CALLTYPE grpcsharp_slice_buffer_adjust_tail_space(
   }
 
   if (buffer->count == 0) {
-    // when sending messages, C-core requires that there
-    // is at least one slice, even for empty payload.
-    // TODO(jtattermusch): this fix can be removed once
-    // https://github.com/grpc/grpc/issues/21299 is fixed.
-    grpc_slice_buffer_add_indexed(buffer, grpc_empty_slice());
+    return NULL;
   }
   grpc_slice* last_slice = &(buffer->slices[buffer->count - 1]);
   return GRPC_SLICE_END_PTR(*last_slice) - requested_tail_space;