diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 366690acf2b0c31b805f802ad3fcc9dc9b0e1116..b95aba14e9ae54d1f3fd9a31b71fc7f69a4e8698 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -239,6 +239,14 @@ static const char *op_id_string(enum e_op_id i) {
   return "UNKNOWN";
 }
 
+static void free_read_buffer(stream_obj *s) {
+  if (s->state.rs.read_buffer &&
+      s->state.rs.read_buffer != s->state.rs.grpc_header_bytes) {
+    gpr_free(s->state.rs.read_buffer);
+    s->state.rs.read_buffer = NULL;
+  }
+}
+
 /*
   Add a new stream op to op storage.
 */
@@ -341,6 +349,7 @@ static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
     gpr_free(s->state.ws.write_buffer);
     s->state.ws.write_buffer = NULL;
   }
+  free_read_buffer(s);
   gpr_mu_unlock(&s->mu);
   execute_from_storage(s);
 }
@@ -363,6 +372,7 @@ static void on_canceled(cronet_bidirectional_stream *stream) {
     gpr_free(s->state.ws.write_buffer);
     s->state.ws.write_buffer = NULL;
   }
+  free_read_buffer(s);
   gpr_mu_unlock(&s->mu);
   execute_from_storage(s);
 }
@@ -377,6 +387,7 @@ static void on_succeeded(cronet_bidirectional_stream *stream) {
   cronet_bidirectional_stream_destroy(s->cbs);
   s->state.state_callback_received[OP_SUCCEEDED] = true;
   s->cbs = NULL;
+  free_read_buffer(s);
   gpr_mu_unlock(&s->mu);
   execute_from_storage(s);
 }
@@ -901,6 +912,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
       uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
       memcpy(dst_p, stream_state->rs.read_buffer,
              (size_t)stream_state->rs.length_field);
+      free_read_buffer(s);
       gpr_slice_buffer_init(&stream_state->rs.read_slice_buffer);
       gpr_slice_buffer_add(&stream_state->rs.read_slice_buffer,
                            read_data_slice);