diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 4146701af6ebbf1780f10e0f1468a9cb7f7d4187..0002253dfee2f12fb774743a865002c8a852452a 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -2665,7 +2665,6 @@ grpc_error *grpc_chttp2_incoming_byte_stream_finished(
   if (error != GRPC_ERROR_NONE && reset_on_error) {
     grpc_closure_sched(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error));
   }
-  GRPC_ERROR_UNREF(error);
   incoming_byte_stream_unref(exec_ctx, bs);
   return error;
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c
index 1f51e0cd6fce2c512c9463e356c5daa6cef3783d..5d382d80a8b7e6bec3719d0a827004ae8d6d9304 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.c
+++ b/src/core/ext/transport/chttp2/transport/frame_data.c
@@ -54,9 +54,9 @@ grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser) {
 void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
                                      grpc_chttp2_data_parser *parser) {
   if (parser->parsing_frame != NULL) {
-    grpc_chttp2_incoming_byte_stream_finished(
+    GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
         exec_ctx, parser->parsing_frame,
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed"), false);
+        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed"), false));
   }
   GRPC_ERROR_UNREF(parser->error);
 }
@@ -213,8 +213,8 @@ grpc_error *deframe_unprocessed_incoming_frames(grpc_exec_ctx *exec_ctx,
             exec_ctx, t, s, p->frame_size, message_flags);
         *stream_out = &p->parsing_frame->base;
         if (p->parsing_frame->remaining_bytes == 0) {
-          grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
-                                                    GRPC_ERROR_NONE, true);
+          GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
+              exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true));
           p->parsing_frame = NULL;
           p->state = GRPC_CHTTP2_DATA_FH_0;
         }
@@ -244,8 +244,12 @@ grpc_error *deframe_unprocessed_incoming_frames(grpc_exec_ctx *exec_ctx,
             grpc_slice_unref_internal(exec_ctx, slice);
             return error;
           }
-          grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
-                                                    GRPC_ERROR_NONE, true);
+          if (GRPC_ERROR_NONE !=
+              (error = grpc_chttp2_incoming_byte_stream_finished(
+                   exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) {
+            grpc_slice_unref_internal(exec_ctx, slice);
+            return error;
+          }
           p->parsing_frame = NULL;
           p->state = GRPC_CHTTP2_DATA_FH_0;
           grpc_slice_unref_internal(exec_ctx, slice);
@@ -272,8 +276,12 @@ grpc_error *deframe_unprocessed_incoming_frames(grpc_exec_ctx *exec_ctx,
             grpc_slice_unref_internal(exec_ctx, slice);
             return error;
           }
-          grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
-                                                    GRPC_ERROR_NONE, true);
+          if (GRPC_ERROR_NONE !=
+              (error = grpc_chttp2_incoming_byte_stream_finished(
+                   exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) {
+            grpc_slice_unref_internal(exec_ctx, slice);
+            return error;
+          }
           p->parsing_frame = NULL;
           p->state = GRPC_CHTTP2_DATA_FH_0;
           cur += p->frame_size;
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index b1cb7f7fb1cfbc524cf2efc489ac2021b1e6d69c..3e96d09798536818593ea8ed18b3ac24d7a99879 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -1226,6 +1226,7 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
   grpc_byte_stream *bs = call->receiving_stream;
+  bool release_error = false;
 
   if (error == GRPC_ERROR_NONE) {
     grpc_slice slice;
@@ -1234,6 +1235,10 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
       grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
                             slice);
       continue_receiving_slices(exec_ctx, bctl);
+    } else {
+      /* Error returned by grpc_byte_stream_pull needs to be released manually
+       */
+      release_error = true;
     }
   }
 
@@ -1247,6 +1252,9 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
     *call->receiving_buffer = NULL;
     call->receiving_message = 0;
     finish_batch_step(exec_ctx, bctl);
+    if (release_error) {
+      GRPC_ERROR_UNREF(error);
+    }
   }
 }