Merge github.com:grpc/grpc into error
diff --git a/BUILD b/BUILD
index f049e3c..ac0eb8e 100644
--- a/BUILD
+++ b/BUILD
@@ -49,7 +49,6 @@
     "src/core/lib/support/backoff.h",
     "src/core/lib/support/block_annotate.h",
     "src/core/lib/support/env.h",
-    "src/core/lib/support/load_file.h",
     "src/core/lib/support/murmur_hash.h",
     "src/core/lib/support/stack_lockfree.h",
     "src/core/lib/support/string.h",
@@ -72,7 +71,6 @@
     "src/core/lib/support/env_windows.c",
     "src/core/lib/support/histogram.c",
     "src/core/lib/support/host_port.c",
-    "src/core/lib/support/load_file.c",
     "src/core/lib/support/log.c",
     "src/core/lib/support/log_android.c",
     "src/core/lib/support/log_linux.c",
@@ -178,6 +176,7 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/error.h",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
@@ -187,6 +186,7 @@
     "src/core/lib/iomgr/iomgr.h",
     "src/core/lib/iomgr/iomgr_internal.h",
     "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/load_file.h",
     "src/core/lib/iomgr/polling_entity.h",
     "src/core/lib/iomgr/pollset.h",
     "src/core/lib/iomgr/pollset_set.h",
@@ -274,6 +274,7 @@
     "src/core/lib/security/transport/handshake.h",
     "src/core/lib/security/transport/secure_endpoint.h",
     "src/core/lib/security/transport/security_connector.h",
+    "src/core/lib/security/transport/tsi_error.h",
     "src/core/lib/security/util/b64.h",
     "src/core/lib/security/util/json_util.h",
     "src/core/lib/tsi/fake_transport_security.h",
@@ -326,6 +327,7 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
+    "src/core/lib/iomgr/error.c",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
@@ -335,6 +337,7 @@
     "src/core/lib/iomgr/iomgr.c",
     "src/core/lib/iomgr/iomgr_posix.c",
     "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/load_file.c",
     "src/core/lib/iomgr/polling_entity.c",
     "src/core/lib/iomgr/pollset_set_windows.c",
     "src/core/lib/iomgr/pollset_windows.c",
@@ -437,6 +440,7 @@
     "src/core/lib/security/transport/secure_endpoint.c",
     "src/core/lib/security/transport/security_connector.c",
     "src/core/lib/security/transport/server_auth_filter.c",
+    "src/core/lib/security/transport/tsi_error.c",
     "src/core/lib/security/util/b64.c",
     "src/core/lib/security/util/json_util.c",
     "src/core/lib/surface/init_secure.c",
@@ -556,6 +560,7 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/error.h",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
@@ -565,6 +570,7 @@
     "src/core/lib/iomgr/iomgr.h",
     "src/core/lib/iomgr/iomgr_internal.h",
     "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/load_file.h",
     "src/core/lib/iomgr/polling_entity.h",
     "src/core/lib/iomgr/pollset.h",
     "src/core/lib/iomgr/pollset_set.h",
@@ -669,6 +675,7 @@
     "src/core/lib/security/transport/handshake.h",
     "src/core/lib/security/transport/secure_endpoint.h",
     "src/core/lib/security/transport/security_connector.h",
+    "src/core/lib/security/transport/tsi_error.h",
     "src/core/lib/security/util/b64.h",
     "src/core/lib/security/util/json_util.h",
     "src/core/lib/tsi/fake_transport_security.h",
@@ -694,6 +701,7 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
+    "src/core/lib/iomgr/error.c",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
@@ -703,6 +711,7 @@
     "src/core/lib/iomgr/iomgr.c",
     "src/core/lib/iomgr/iomgr_posix.c",
     "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/load_file.c",
     "src/core/lib/iomgr/polling_entity.c",
     "src/core/lib/iomgr/pollset_set_windows.c",
     "src/core/lib/iomgr/pollset_windows.c",
@@ -827,6 +836,7 @@
     "src/core/lib/security/transport/secure_endpoint.c",
     "src/core/lib/security/transport/security_connector.c",
     "src/core/lib/security/transport/server_auth_filter.c",
+    "src/core/lib/security/transport/tsi_error.c",
     "src/core/lib/security/util/b64.c",
     "src/core/lib/security/util/json_util.c",
     "src/core/lib/surface/init_secure.c",
@@ -899,6 +909,7 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/error.h",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
@@ -908,6 +919,7 @@
     "src/core/lib/iomgr/iomgr.h",
     "src/core/lib/iomgr/iomgr_internal.h",
     "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/load_file.h",
     "src/core/lib/iomgr/polling_entity.h",
     "src/core/lib/iomgr/pollset.h",
     "src/core/lib/iomgr/pollset_set.h",
@@ -1025,6 +1037,7 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
+    "src/core/lib/iomgr/error.c",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
@@ -1034,6 +1047,7 @@
     "src/core/lib/iomgr/iomgr.c",
     "src/core/lib/iomgr/iomgr_posix.c",
     "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/load_file.c",
     "src/core/lib/iomgr/polling_entity.c",
     "src/core/lib/iomgr/pollset_set_windows.c",
     "src/core/lib/iomgr/pollset_windows.c",
@@ -1203,26 +1217,6 @@
 
 
 cc_library(
-  name = "grpc_zookeeper",
-  srcs = [
-    "src/core/ext/resolver/zookeeper/zookeeper_resolver.c",
-  ],
-  hdrs = [
-    "include/grpc/grpc_zookeeper.h",
-  ],
-  includes = [
-    "include",
-    ".",
-  ],
-  deps = [
-    ":gpr",
-    ":grpc",
-  ],
-)
-
-
-
-cc_library(
   name = "grpc++",
   srcs = [
     "include/grpc++/impl/codegen/core_codegen.h",
@@ -1683,7 +1677,6 @@
     "src/core/lib/support/env_windows.c",
     "src/core/lib/support/histogram.c",
     "src/core/lib/support/host_port.c",
-    "src/core/lib/support/load_file.c",
     "src/core/lib/support/log.c",
     "src/core/lib/support/log_android.c",
     "src/core/lib/support/log_linux.c",
@@ -1762,7 +1755,6 @@
     "src/core/lib/support/backoff.h",
     "src/core/lib/support/block_annotate.h",
     "src/core/lib/support/env.h",
-    "src/core/lib/support/load_file.h",
     "src/core/lib/support/murmur_hash.h",
     "src/core/lib/support/stack_lockfree.h",
     "src/core/lib/support/string.h",
@@ -1802,6 +1794,7 @@
     "src/core/lib/iomgr/endpoint.c",
     "src/core/lib/iomgr/endpoint_pair_posix.c",
     "src/core/lib/iomgr/endpoint_pair_windows.c",
+    "src/core/lib/iomgr/error.c",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
     "src/core/lib/iomgr/ev_poll_posix.c",
     "src/core/lib/iomgr/ev_posix.c",
@@ -1811,6 +1804,7 @@
     "src/core/lib/iomgr/iomgr.c",
     "src/core/lib/iomgr/iomgr_posix.c",
     "src/core/lib/iomgr/iomgr_windows.c",
+    "src/core/lib/iomgr/load_file.c",
     "src/core/lib/iomgr/polling_entity.c",
     "src/core/lib/iomgr/pollset_set_windows.c",
     "src/core/lib/iomgr/pollset_windows.c",
@@ -1913,6 +1907,7 @@
     "src/core/lib/security/transport/secure_endpoint.c",
     "src/core/lib/security/transport/security_connector.c",
     "src/core/lib/security/transport/server_auth_filter.c",
+    "src/core/lib/security/transport/tsi_error.c",
     "src/core/lib/security/util/b64.c",
     "src/core/lib/security/util/json_util.c",
     "src/core/lib/surface/init_secure.c",
@@ -2011,6 +2006,7 @@
     "src/core/lib/iomgr/closure.h",
     "src/core/lib/iomgr/endpoint.h",
     "src/core/lib/iomgr/endpoint_pair.h",
+    "src/core/lib/iomgr/error.h",
     "src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
     "src/core/lib/iomgr/ev_poll_posix.h",
     "src/core/lib/iomgr/ev_posix.h",
@@ -2020,6 +2016,7 @@
     "src/core/lib/iomgr/iomgr.h",
     "src/core/lib/iomgr/iomgr_internal.h",
     "src/core/lib/iomgr/iomgr_posix.h",
+    "src/core/lib/iomgr/load_file.h",
     "src/core/lib/iomgr/polling_entity.h",
     "src/core/lib/iomgr/pollset.h",
     "src/core/lib/iomgr/pollset_set.h",
@@ -2107,6 +2104,7 @@
     "src/core/lib/security/transport/handshake.h",
     "src/core/lib/security/transport/secure_endpoint.h",
     "src/core/lib/security/transport/security_connector.h",
+    "src/core/lib/security/transport/tsi_error.h",
     "src/core/lib/security/util/b64.h",
     "src/core/lib/security/util/json_util.h",
     "src/core/lib/tsi/fake_transport_security.h",
diff --git a/Makefile b/Makefile
index 6eccd06..dcdecd3 100644
--- a/Makefile
+++ b/Makefile
@@ -920,7 +920,6 @@
 gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
 gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test
 gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
-gpr_load_file_test: $(BINDIR)/$(CONFIG)/gpr_load_file_test
 gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
 gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test
 gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test
@@ -949,8 +948,9 @@
 hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
 hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
 hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test
-http_fuzzer_test: $(BINDIR)/$(CONFIG)/http_fuzzer_test
 http_parser_test: $(BINDIR)/$(CONFIG)/http_parser_test
+http_request_fuzzer_test: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test
+http_response_fuzzer_test: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test
 httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test
 httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test
 httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test
@@ -966,6 +966,7 @@
 json_test: $(BINDIR)/$(CONFIG)/json_test
 lame_client_test: $(BINDIR)/$(CONFIG)/lame_client_test
 lb_policies_test: $(BINDIR)/$(CONFIG)/lb_policies_test
+load_file_test: $(BINDIR)/$(CONFIG)/load_file_test
 low_level_ping_pong_benchmark: $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark
 message_compress_test: $(BINDIR)/$(CONFIG)/message_compress_test
 mlog_test: $(BINDIR)/$(CONFIG)/mlog_test
@@ -977,6 +978,7 @@
 resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
 secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
 secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test
+sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test
 server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
 server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
 server_test: $(BINDIR)/$(CONFIG)/server_test
@@ -1048,7 +1050,6 @@
 streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
 stress_test: $(BINDIR)/$(CONFIG)/stress_test
 thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
-zookeeper_test: $(BINDIR)/$(CONFIG)/zookeeper_test
 public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
 boringssl_aes_test: $(BINDIR)/$(CONFIG)/boringssl_aes_test
 boringssl_asn1_test: $(BINDIR)/$(CONFIG)/boringssl_asn1_test
@@ -1134,7 +1135,8 @@
 api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
 client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
 hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
-http_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
+http_request_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry
+http_response_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry
 json_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry
 nanopb_fuzzer_response_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry
 nanopb_fuzzer_serverlist_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry
@@ -1180,8 +1182,8 @@
 
 shared_csharp: shared_c  $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT)
 ifeq ($(HAS_ZOOKEEPER),true)
-static_zookeeper_libs: $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
-shared_zookeeper_libs: $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
+static_zookeeper_libs:
+shared_zookeeper_libs:
 else
 
 static_zookeeper_libs:
@@ -1255,7 +1257,6 @@
   $(BINDIR)/$(CONFIG)/gpr_env_test \
   $(BINDIR)/$(CONFIG)/gpr_histogram_test \
   $(BINDIR)/$(CONFIG)/gpr_host_port_test \
-  $(BINDIR)/$(CONFIG)/gpr_load_file_test \
   $(BINDIR)/$(CONFIG)/gpr_log_test \
   $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \
   $(BINDIR)/$(CONFIG)/gpr_slice_test \
@@ -1294,6 +1295,7 @@
   $(BINDIR)/$(CONFIG)/json_test \
   $(BINDIR)/$(CONFIG)/lame_client_test \
   $(BINDIR)/$(CONFIG)/lb_policies_test \
+  $(BINDIR)/$(CONFIG)/load_file_test \
   $(BINDIR)/$(CONFIG)/message_compress_test \
   $(BINDIR)/$(CONFIG)/mlog_test \
   $(BINDIR)/$(CONFIG)/multiple_server_queues_test \
@@ -1302,6 +1304,7 @@
   $(BINDIR)/$(CONFIG)/resolve_address_test \
   $(BINDIR)/$(CONFIG)/secure_channel_create_test \
   $(BINDIR)/$(CONFIG)/secure_endpoint_test \
+  $(BINDIR)/$(CONFIG)/sequential_connectivity_test \
   $(BINDIR)/$(CONFIG)/server_chttp2_test \
   $(BINDIR)/$(CONFIG)/server_test \
   $(BINDIR)/$(CONFIG)/set_initial_connect_string_test \
@@ -1369,7 +1372,8 @@
   $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
-  $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry \
+  $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry \
+  $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry \
   $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry \
   $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry \
   $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry \
@@ -1463,7 +1467,6 @@
 
 ifeq ($(HAS_ZOOKEEPER),true)
 buildtests_zookeeper: privatelibs_zookeeper \
- $(BINDIR)/$(CONFIG)/zookeeper_test \
 
 else
 buildtests_zookeeper:
@@ -1535,8 +1538,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_histogram_test || ( echo test gpr_histogram_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_host_port_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_test failed ; exit 1 )
-	$(E) "[RUN]     Testing gpr_load_file_test"
-	$(Q) $(BINDIR)/$(CONFIG)/gpr_load_file_test || ( echo test gpr_load_file_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_log_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_slice_buffer_test"
@@ -1603,6 +1604,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/json_test || ( echo test json_test failed ; exit 1 )
 	$(E) "[RUN]     Testing lame_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/lame_client_test || ( echo test lame_client_test failed ; exit 1 )
+	$(E) "[RUN]     Testing load_file_test"
+	$(Q) $(BINDIR)/$(CONFIG)/load_file_test || ( echo test load_file_test failed ; exit 1 )
 	$(E) "[RUN]     Testing message_compress_test"
 	$(Q) $(BINDIR)/$(CONFIG)/message_compress_test || ( echo test message_compress_test failed ; exit 1 )
 	$(E) "[RUN]     Testing multiple_server_queues_test"
@@ -1617,6 +1620,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/secure_channel_create_test || ( echo test secure_channel_create_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_endpoint_test"
 	$(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 )
+	$(E) "[RUN]     Testing sequential_connectivity_test"
+	$(Q) $(BINDIR)/$(CONFIG)/sequential_connectivity_test || ( echo test sequential_connectivity_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_chttp2_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_test"
@@ -1808,8 +1813,6 @@
 	$(E) "[STRIP]   Stripping libgrpc_unsecure.a"
 	$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a
 ifeq ($(HAS_ZOOKEEPER),true)
-	$(E) "[STRIP]   Stripping libgrpc_zookeeper.a"
-	$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
 endif
 endif
 
@@ -1834,8 +1837,6 @@
 	$(E) "[STRIP]   Stripping $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT)"
 	$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT)
 ifeq ($(HAS_ZOOKEEPER),true)
-	$(E) "[STRIP]   Stripping $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)"
-	$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
 endif
 endif
 
@@ -2150,9 +2151,6 @@
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a
 ifeq ($(HAS_ZOOKEEPER),true)
-	$(E) "[INSTALL] Installing libgrpc_zookeeper.a"
-	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(prefix)/lib/libgrpc_zookeeper.a
 endif
 
 install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
@@ -2206,15 +2204,6 @@
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_unsecure.so
 endif
 ifeq ($(HAS_ZOOKEEPER),true)
-	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)"
-	$(Q) $(INSTALL) -d $(prefix)/lib
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
-ifeq ($(SYSTEM),MINGW32)
-	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper-imp.a $(prefix)/lib/libgrpc_zookeeper-imp.a
-else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_zookeeper.so.0
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_zookeeper.so
-endif
 endif
 ifneq ($(SYSTEM),MINGW32)
 ifneq ($(SYSTEM),Darwin)
@@ -2364,7 +2353,6 @@
     src/core/lib/support/env_windows.c \
     src/core/lib/support/histogram.c \
     src/core/lib/support/host_port.c \
-    src/core/lib/support/load_file.c \
     src/core/lib/support/log.c \
     src/core/lib/support/log_android.c \
     src/core/lib/support/log_linux.c \
@@ -2521,6 +2509,7 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
+    src/core/lib/iomgr/error.c \
     src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
@@ -2530,6 +2519,7 @@
     src/core/lib/iomgr/iomgr.c \
     src/core/lib/iomgr/iomgr_posix.c \
     src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/load_file.c \
     src/core/lib/iomgr/polling_entity.c \
     src/core/lib/iomgr/pollset_set_windows.c \
     src/core/lib/iomgr/pollset_windows.c \
@@ -2632,6 +2622,7 @@
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/server_auth_filter.c \
+    src/core/lib/security/transport/tsi_error.c \
     src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
@@ -2788,6 +2779,7 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
+    src/core/lib/iomgr/error.c \
     src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
@@ -2797,6 +2789,7 @@
     src/core/lib/iomgr/iomgr.c \
     src/core/lib/iomgr/iomgr_posix.c \
     src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/load_file.c \
     src/core/lib/iomgr/polling_entity.c \
     src/core/lib/iomgr/pollset_set_windows.c \
     src/core/lib/iomgr/pollset_windows.c \
@@ -2921,6 +2914,7 @@
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/server_auth_filter.c \
+    src/core/lib/security/transport/tsi_error.c \
     src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
@@ -3124,6 +3118,7 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
+    src/core/lib/iomgr/error.c \
     src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
@@ -3133,6 +3128,7 @@
     src/core/lib/iomgr/iomgr.c \
     src/core/lib/iomgr/iomgr_posix.c \
     src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/load_file.c \
     src/core/lib/iomgr/polling_entity.c \
     src/core/lib/iomgr/pollset_set_windows.c \
     src/core/lib/iomgr/pollset_windows.c \
@@ -3326,49 +3322,6 @@
 endif
 
 
-LIBGRPC_ZOOKEEPER_SRC = \
-    src/core/ext/resolver/zookeeper/zookeeper_resolver.c \
-
-PUBLIC_HEADERS_C += \
-    include/grpc/grpc_zookeeper.h \
-
-LIBGRPC_ZOOKEEPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_ZOOKEEPER_SRC))))
-
-
-$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a: $(ZLIB_DEP)  $(LIBGRPC_ZOOKEEPER_OBJS) 
-	$(E) "[AR]      Creating $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
-	$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBGRPC_ZOOKEEPER_OBJS) 
-ifeq ($(SYSTEM),Darwin)
-	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
-endif
-
-
-
-ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC_ZOOKEEPER_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT)
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_zookeeper.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr-imp -lgrpc-imp
-else
-$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC_ZOOKEEPER_OBJS)  $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT)
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr -lgrpc -lzookeeper_mt
-else
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_zookeeper.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr -lgrpc -lzookeeper_mt
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).so.0
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).so
-endif
-endif
-
-ifneq ($(NO_DEPS),true)
--include $(LIBGRPC_ZOOKEEPER_OBJS:.o=.dep)
-endif
-
-
 LIBRECONNECT_SERVER_SRC = \
     test/core/util/reconnect_server.c \
 
@@ -7638,38 +7591,6 @@
 endif
 
 
-GPR_LOAD_FILE_TEST_SRC = \
-    test/core/support/load_file_test.c \
-
-GPR_LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOAD_FILE_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/gpr_load_file_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_load_file_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/support/load_file_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 GPR_LOG_TEST_SRC = \
     test/core/support/log_test.c \
 
@@ -8566,38 +8487,6 @@
 endif
 
 
-HTTP_FUZZER_TEST_SRC = \
-    test/core/http/fuzzer.c \
-
-HTTP_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/http_fuzzer_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(HTTP_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_fuzzer_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 HTTP_PARSER_TEST_SRC = \
     test/core/http/parser_test.c \
 
@@ -8630,6 +8519,70 @@
 endif
 
 
+HTTP_REQUEST_FUZZER_TEST_SRC = \
+    test/core/http/request_fuzzer.c \
+
+HTTP_REQUEST_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_request_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(HTTP_REQUEST_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_request_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+HTTP_RESPONSE_FUZZER_TEST_SRC = \
+    test/core/http/response_fuzzer.c \
+
+HTTP_RESPONSE_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_response_fuzzer_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(HTTP_RESPONSE_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_response_fuzzer_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 HTTPCLI_FORMAT_REQUEST_TEST_SRC = \
     test/core/http/format_request_test.c \
 
@@ -9110,6 +9063,38 @@
 endif
 
 
+LOAD_FILE_TEST_SRC = \
+    test/core/iomgr/load_file_test.c \
+
+LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOAD_FILE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/load_file_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/load_file_test: $(LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/load_file_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/iomgr/load_file_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_load_file_test: $(LOAD_FILE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LOAD_FILE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 LOW_LEVEL_PING_PONG_BENCHMARK_SRC = \
     test/core/network_benchmarks/low_level_ping_pong.c \
 
@@ -9462,6 +9447,38 @@
 endif
 
 
+SEQUENTIAL_CONNECTIVITY_TEST_SRC = \
+    test/core/surface/sequential_connectivity_test.c \
+
+SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/sequential_connectivity_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/sequential_connectivity_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/surface/sequential_connectivity_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 SERVER_CHTTP2_TEST_SRC = \
     test/core/surface/server_chttp2_test.c \
 
@@ -12273,53 +12290,6 @@
 endif
 
 
-ZOOKEEPER_TEST_SRC = \
-    $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
-    test/cpp/end2end/zookeeper_test.cc \
-
-ZOOKEEPER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ZOOKEEPER_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/zookeeper_test: openssl_dep_error
-
-else
-
-
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/zookeeper_test: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/zookeeper_test: $(PROTOBUF_DEP) $(ZOOKEEPER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(ZOOKEEPER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -lzookeeper_mt $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/zookeeper_test
-
-endif
-
-endif
-
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-$(OBJDIR)/$(CONFIG)/test/cpp/end2end/zookeeper_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_zookeeper_test: $(ZOOKEEPER_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(ZOOKEEPER_TEST_OBJS:.o=.dep)
-endif
-endif
-$(OBJDIR)/$(CONFIG)/test/cpp/end2end/zookeeper_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc
-
-
 PUBLIC_HEADERS_MUST_BE_C89_SRC = \
     test/core/surface/public_headers_must_be_c89.c \
 
@@ -14599,37 +14569,72 @@
 endif
 
 
-HTTP_FUZZER_TEST_ONE_ENTRY_SRC = \
-    test/core/http/fuzzer.c \
+HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/http/request_fuzzer.c \
     test/core/util/one_corpus_entry_fuzzer.c \
 
-HTTP_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_ONE_ENTRY_SRC))))
+HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: openssl_dep_error
+$(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
+	$(Q) $(LD) $(LDFLAGS) $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 $(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+deps_http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+-include $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
+HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC = \
+    test/core/http/response_fuzzer.c \
+    test/core/util/one_corpus_entry_fuzzer.c \
+
+HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
 endif
 endif
 
@@ -14843,6 +14848,7 @@
 src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/tsi_error.c: $(OPENSSL_DEP)
 src/core/lib/security/util/b64.c: $(OPENSSL_DEP)
 src/core/lib/security/util/json_util.c: $(OPENSSL_DEP)
 src/core/lib/surface/init_secure.c: $(OPENSSL_DEP)
diff --git a/binding.gyp b/binding.gyp
index fc61a9d..3150d10 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -510,7 +510,6 @@
         'src/core/lib/support/env_windows.c',
         'src/core/lib/support/histogram.c',
         'src/core/lib/support/host_port.c',
-        'src/core/lib/support/load_file.c',
         'src/core/lib/support/log.c',
         'src/core/lib/support/log_android.c',
         'src/core/lib/support/log_linux.c',
@@ -581,6 +580,7 @@
         'src/core/lib/iomgr/endpoint.c',
         'src/core/lib/iomgr/endpoint_pair_posix.c',
         'src/core/lib/iomgr/endpoint_pair_windows.c',
+        'src/core/lib/iomgr/error.c',
         'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
         'src/core/lib/iomgr/ev_poll_posix.c',
         'src/core/lib/iomgr/ev_posix.c',
@@ -590,6 +590,7 @@
         'src/core/lib/iomgr/iomgr.c',
         'src/core/lib/iomgr/iomgr_posix.c',
         'src/core/lib/iomgr/iomgr_windows.c',
+        'src/core/lib/iomgr/load_file.c',
         'src/core/lib/iomgr/polling_entity.c',
         'src/core/lib/iomgr/pollset_set_windows.c',
         'src/core/lib/iomgr/pollset_windows.c',
@@ -692,6 +693,7 @@
         'src/core/lib/security/transport/secure_endpoint.c',
         'src/core/lib/security/transport/security_connector.c',
         'src/core/lib/security/transport/server_auth_filter.c',
+        'src/core/lib/security/transport/tsi_error.c',
         'src/core/lib/security/util/b64.c',
         'src/core/lib/security/util/json_util.c',
         'src/core/lib/surface/init_secure.c',
diff --git a/build.yaml b/build.yaml
index a83ebc5..38fb2c9 100644
--- a/build.yaml
+++ b/build.yaml
@@ -70,7 +70,6 @@
   - src/core/lib/support/backoff.h
   - src/core/lib/support/block_annotate.h
   - src/core/lib/support/env.h
-  - src/core/lib/support/load_file.h
   - src/core/lib/support/murmur_hash.h
   - src/core/lib/support/stack_lockfree.h
   - src/core/lib/support/string.h
@@ -94,7 +93,6 @@
   - src/core/lib/support/env_windows.c
   - src/core/lib/support/histogram.c
   - src/core/lib/support/host_port.c
-  - src/core/lib/support/load_file.c
   - src/core/lib/support/log.c
   - src/core/lib/support/log_android.c
   - src/core/lib/support/log_linux.c
@@ -174,6 +172,7 @@
   - src/core/lib/iomgr/closure.h
   - src/core/lib/iomgr/endpoint.h
   - src/core/lib/iomgr/endpoint_pair.h
+  - src/core/lib/iomgr/error.h
   - src/core/lib/iomgr/ev_poll_and_epoll_posix.h
   - src/core/lib/iomgr/ev_poll_posix.h
   - src/core/lib/iomgr/ev_posix.h
@@ -183,6 +182,7 @@
   - src/core/lib/iomgr/iomgr.h
   - src/core/lib/iomgr/iomgr_internal.h
   - src/core/lib/iomgr/iomgr_posix.h
+  - src/core/lib/iomgr/load_file.h
   - src/core/lib/iomgr/polling_entity.h
   - src/core/lib/iomgr/pollset.h
   - src/core/lib/iomgr/pollset_set.h
@@ -250,6 +250,7 @@
   - src/core/lib/iomgr/endpoint.c
   - src/core/lib/iomgr/endpoint_pair_posix.c
   - src/core/lib/iomgr/endpoint_pair_windows.c
+  - src/core/lib/iomgr/error.c
   - src/core/lib/iomgr/ev_poll_and_epoll_posix.c
   - src/core/lib/iomgr/ev_poll_posix.c
   - src/core/lib/iomgr/ev_posix.c
@@ -259,6 +260,7 @@
   - src/core/lib/iomgr/iomgr.c
   - src/core/lib/iomgr/iomgr_posix.c
   - src/core/lib/iomgr/iomgr_windows.c
+  - src/core/lib/iomgr/load_file.c
   - src/core/lib/iomgr/polling_entity.c
   - src/core/lib/iomgr/pollset_set_windows.c
   - src/core/lib/iomgr/pollset_windows.c
@@ -442,6 +444,7 @@
   - src/core/lib/security/transport/handshake.h
   - src/core/lib/security/transport/secure_endpoint.h
   - src/core/lib/security/transport/security_connector.h
+  - src/core/lib/security/transport/tsi_error.h
   - src/core/lib/security/util/b64.h
   - src/core/lib/security/util/json_util.h
   src:
@@ -466,6 +469,7 @@
   - src/core/lib/security/transport/secure_endpoint.c
   - src/core/lib/security/transport/security_connector.c
   - src/core/lib/security/transport/server_auth_filter.c
+  - src/core/lib/security/transport/tsi_error.c
   - src/core/lib/security/util/b64.c
   - src/core/lib/security/util/json_util.c
   - src/core/lib/surface/init_secure.c
@@ -897,21 +901,6 @@
   generate_plugin_registry: true
   secure: false
   vs_project_guid: '{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}'
-- name: grpc_zookeeper
-  build: all
-  language: c
-  public_headers:
-  - include/grpc/grpc_zookeeper.h
-  src:
-  - src/core/ext/resolver/zookeeper/zookeeper_resolver.c
-  deps:
-  - gpr
-  - grpc
-  external_deps:
-  - zookeeper
-  platforms:
-  - linux
-  secure: false
 - name: reconnect_server
   build: private
   language: c
@@ -1570,14 +1559,6 @@
   deps:
   - gpr_test_util
   - gpr
-- name: gpr_load_file_test
-  build: test
-  language: c
-  src:
-  - test/core/support/load_file_test.c
-  deps:
-  - gpr_test_util
-  - gpr
 - name: gpr_log_test
   build: test
   language: c
@@ -1849,19 +1830,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: http_fuzzer_test
-  build: fuzzer
-  language: c
-  src:
-  - test/core/http/fuzzer.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
-  corpus_dirs:
-  - test/core/http/corpus
-  maxlen: 2048
 - name: http_parser_test
   build: test
   language: c
@@ -1872,6 +1840,32 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: http_request_fuzzer_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/http/request_fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/http/corpus
+  maxlen: 2048
+- name: http_response_fuzzer_test
+  build: fuzzer
+  language: c
+  src:
+  - test/core/http/response_fuzzer.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/http/corpus
+  maxlen: 2048
 - name: httpcli_format_request_test
   build: test
   language: c
@@ -2037,6 +2031,16 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: load_file_test
+  build: test
+  language: c
+  src:
+  - test/core/iomgr/load_file_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: low_level_ping_pong_benchmark
   build: benchmark
   language: c
@@ -2157,6 +2161,16 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: sequential_connectivity_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/sequential_connectivity_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: server_chttp2_test
   build: test
   language: c
@@ -3104,26 +3118,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: zookeeper_test
-  gtest: true
-  build: test
-  run: false
-  language: c++
-  src:
-  - src/proto/grpc/testing/echo.proto
-  - test/cpp/end2end/zookeeper_test.cc
-  deps:
-  - grpc++_test_util
-  - grpc_test_util
-  - grpc++
-  - grpc_zookeeper
-  - grpc
-  - gpr_test_util
-  - gpr
-  external_deps:
-  - zookeeper
-  platforms:
-  - linux
 - name: public_headers_must_be_c89
   build: test
   language: c89
diff --git a/config.m4 b/config.m4
index bf5aa24..716eb98 100644
--- a/config.m4
+++ b/config.m4
@@ -51,7 +51,6 @@
     src/core/lib/support/env_windows.c \
     src/core/lib/support/histogram.c \
     src/core/lib/support/host_port.c \
-    src/core/lib/support/load_file.c \
     src/core/lib/support/log.c \
     src/core/lib/support/log_android.c \
     src/core/lib/support/log_linux.c \
@@ -100,6 +99,7 @@
     src/core/lib/iomgr/endpoint.c \
     src/core/lib/iomgr/endpoint_pair_posix.c \
     src/core/lib/iomgr/endpoint_pair_windows.c \
+    src/core/lib/iomgr/error.c \
     src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
     src/core/lib/iomgr/ev_poll_posix.c \
     src/core/lib/iomgr/ev_posix.c \
@@ -109,6 +109,7 @@
     src/core/lib/iomgr/iomgr.c \
     src/core/lib/iomgr/iomgr_posix.c \
     src/core/lib/iomgr/iomgr_windows.c \
+    src/core/lib/iomgr/load_file.c \
     src/core/lib/iomgr/polling_entity.c \
     src/core/lib/iomgr/pollset_set_windows.c \
     src/core/lib/iomgr/pollset_windows.c \
@@ -211,6 +212,7 @@
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/server_auth_filter.c \
+    src/core/lib/security/transport/tsi_error.c \
     src/core/lib/security/util/b64.c \
     src/core/lib/security/util/json_util.c \
     src/core/lib/surface/init_secure.c \
diff --git a/gRPC.podspec b/gRPC.podspec
index d3665d5..ff83736 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -68,7 +68,6 @@
                       'src/core/lib/support/backoff.h',
                       'src/core/lib/support/block_annotate.h',
                       'src/core/lib/support/env.h',
-                      'src/core/lib/support/load_file.h',
                       'src/core/lib/support/murmur_hash.h',
                       'src/core/lib/support/stack_lockfree.h',
                       'src/core/lib/support/string.h',
@@ -133,7 +132,6 @@
                       'src/core/lib/support/env_windows.c',
                       'src/core/lib/support/histogram.c',
                       'src/core/lib/support/host_port.c',
-                      'src/core/lib/support/load_file.c',
                       'src/core/lib/support/log.c',
                       'src/core/lib/support/log_android.c',
                       'src/core/lib/support/log_linux.c',
@@ -181,6 +179,7 @@
                       'src/core/lib/iomgr/closure.h',
                       'src/core/lib/iomgr/endpoint.h',
                       'src/core/lib/iomgr/endpoint_pair.h',
+                      'src/core/lib/iomgr/error.h',
                       'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
                       'src/core/lib/iomgr/ev_poll_posix.h',
                       'src/core/lib/iomgr/ev_posix.h',
@@ -190,6 +189,7 @@
                       'src/core/lib/iomgr/iomgr.h',
                       'src/core/lib/iomgr/iomgr_internal.h',
                       'src/core/lib/iomgr/iomgr_posix.h',
+                      'src/core/lib/iomgr/load_file.h',
                       'src/core/lib/iomgr/polling_entity.h',
                       'src/core/lib/iomgr/pollset.h',
                       'src/core/lib/iomgr/pollset_set.h',
@@ -277,6 +277,7 @@
                       'src/core/lib/security/transport/handshake.h',
                       'src/core/lib/security/transport/secure_endpoint.h',
                       'src/core/lib/security/transport/security_connector.h',
+                      'src/core/lib/security/transport/tsi_error.h',
                       'src/core/lib/security/util/b64.h',
                       'src/core/lib/security/util/json_util.h',
                       'src/core/lib/tsi/fake_transport_security.h',
@@ -363,6 +364,7 @@
                       'src/core/lib/iomgr/endpoint.c',
                       'src/core/lib/iomgr/endpoint_pair_posix.c',
                       'src/core/lib/iomgr/endpoint_pair_windows.c',
+                      'src/core/lib/iomgr/error.c',
                       'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
                       'src/core/lib/iomgr/ev_poll_posix.c',
                       'src/core/lib/iomgr/ev_posix.c',
@@ -372,6 +374,7 @@
                       'src/core/lib/iomgr/iomgr.c',
                       'src/core/lib/iomgr/iomgr_posix.c',
                       'src/core/lib/iomgr/iomgr_windows.c',
+                      'src/core/lib/iomgr/load_file.c',
                       'src/core/lib/iomgr/polling_entity.c',
                       'src/core/lib/iomgr/pollset_set_windows.c',
                       'src/core/lib/iomgr/pollset_windows.c',
@@ -474,6 +477,7 @@
                       'src/core/lib/security/transport/secure_endpoint.c',
                       'src/core/lib/security/transport/security_connector.c',
                       'src/core/lib/security/transport/server_auth_filter.c',
+                      'src/core/lib/security/transport/tsi_error.c',
                       'src/core/lib/security/util/b64.c',
                       'src/core/lib/security/util/json_util.c',
                       'src/core/lib/surface/init_secure.c',
@@ -531,7 +535,6 @@
                               'src/core/lib/support/backoff.h',
                               'src/core/lib/support/block_annotate.h',
                               'src/core/lib/support/env.h',
-                              'src/core/lib/support/load_file.h',
                               'src/core/lib/support/murmur_hash.h',
                               'src/core/lib/support/stack_lockfree.h',
                               'src/core/lib/support/string.h',
@@ -556,6 +559,7 @@
                               'src/core/lib/iomgr/closure.h',
                               'src/core/lib/iomgr/endpoint.h',
                               'src/core/lib/iomgr/endpoint_pair.h',
+                              'src/core/lib/iomgr/error.h',
                               'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
                               'src/core/lib/iomgr/ev_poll_posix.h',
                               'src/core/lib/iomgr/ev_posix.h',
@@ -565,6 +569,7 @@
                               'src/core/lib/iomgr/iomgr.h',
                               'src/core/lib/iomgr/iomgr_internal.h',
                               'src/core/lib/iomgr/iomgr_posix.h',
+                              'src/core/lib/iomgr/load_file.h',
                               'src/core/lib/iomgr/polling_entity.h',
                               'src/core/lib/iomgr/pollset.h',
                               'src/core/lib/iomgr/pollset_set.h',
@@ -652,6 +657,7 @@
                               'src/core/lib/security/transport/handshake.h',
                               'src/core/lib/security/transport/secure_endpoint.h',
                               'src/core/lib/security/transport/security_connector.h',
+                              'src/core/lib/security/transport/tsi_error.h',
                               'src/core/lib/security/util/b64.h',
                               'src/core/lib/security/util/json_util.h',
                               'src/core/lib/tsi/fake_transport_security.h',
diff --git a/grpc.def b/grpc.def
index 0046028..95030ad 100644
--- a/grpc.def
+++ b/grpc.def
@@ -222,6 +222,8 @@
     gpr_avl_add
     gpr_avl_remove
     gpr_avl_get
+    gpr_avl_maybe_get
+    gpr_avl_is_empty
     gpr_cmdline_create
     gpr_cmdline_add_int
     gpr_cmdline_add_flag
diff --git a/grpc.gemspec b/grpc.gemspec
index 9f3ae04..184a548 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -89,7 +89,6 @@
   s.files += %w( src/core/lib/support/backoff.h )
   s.files += %w( src/core/lib/support/block_annotate.h )
   s.files += %w( src/core/lib/support/env.h )
-  s.files += %w( src/core/lib/support/load_file.h )
   s.files += %w( src/core/lib/support/murmur_hash.h )
   s.files += %w( src/core/lib/support/stack_lockfree.h )
   s.files += %w( src/core/lib/support/string.h )
@@ -112,7 +111,6 @@
   s.files += %w( src/core/lib/support/env_windows.c )
   s.files += %w( src/core/lib/support/histogram.c )
   s.files += %w( src/core/lib/support/host_port.c )
-  s.files += %w( src/core/lib/support/load_file.c )
   s.files += %w( src/core/lib/support/log.c )
   s.files += %w( src/core/lib/support/log_android.c )
   s.files += %w( src/core/lib/support/log_linux.c )
@@ -190,6 +188,7 @@
   s.files += %w( src/core/lib/iomgr/closure.h )
   s.files += %w( src/core/lib/iomgr/endpoint.h )
   s.files += %w( src/core/lib/iomgr/endpoint_pair.h )
+  s.files += %w( src/core/lib/iomgr/error.h )
   s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h )
   s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
   s.files += %w( src/core/lib/iomgr/ev_posix.h )
@@ -199,6 +198,7 @@
   s.files += %w( src/core/lib/iomgr/iomgr.h )
   s.files += %w( src/core/lib/iomgr/iomgr_internal.h )
   s.files += %w( src/core/lib/iomgr/iomgr_posix.h )
+  s.files += %w( src/core/lib/iomgr/load_file.h )
   s.files += %w( src/core/lib/iomgr/polling_entity.h )
   s.files += %w( src/core/lib/iomgr/pollset.h )
   s.files += %w( src/core/lib/iomgr/pollset_set.h )
@@ -286,6 +286,7 @@
   s.files += %w( src/core/lib/security/transport/handshake.h )
   s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
   s.files += %w( src/core/lib/security/transport/security_connector.h )
+  s.files += %w( src/core/lib/security/transport/tsi_error.h )
   s.files += %w( src/core/lib/security/util/b64.h )
   s.files += %w( src/core/lib/security/util/json_util.h )
   s.files += %w( src/core/lib/tsi/fake_transport_security.h )
@@ -342,6 +343,7 @@
   s.files += %w( src/core/lib/iomgr/endpoint.c )
   s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c )
   s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c )
+  s.files += %w( src/core/lib/iomgr/error.c )
   s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c )
   s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )
   s.files += %w( src/core/lib/iomgr/ev_posix.c )
@@ -351,6 +353,7 @@
   s.files += %w( src/core/lib/iomgr/iomgr.c )
   s.files += %w( src/core/lib/iomgr/iomgr_posix.c )
   s.files += %w( src/core/lib/iomgr/iomgr_windows.c )
+  s.files += %w( src/core/lib/iomgr/load_file.c )
   s.files += %w( src/core/lib/iomgr/polling_entity.c )
   s.files += %w( src/core/lib/iomgr/pollset_set_windows.c )
   s.files += %w( src/core/lib/iomgr/pollset_windows.c )
@@ -453,6 +456,7 @@
   s.files += %w( src/core/lib/security/transport/secure_endpoint.c )
   s.files += %w( src/core/lib/security/transport/security_connector.c )
   s.files += %w( src/core/lib/security/transport/server_auth_filter.c )
+  s.files += %w( src/core/lib/security/transport/tsi_error.c )
   s.files += %w( src/core/lib/security/util/b64.c )
   s.files += %w( src/core/lib/security/util/json_util.c )
   s.files += %w( src/core/lib/surface/init_secure.c )
diff --git a/include/grpc/support/avl.h b/include/grpc/support/avl.h
index d71592d..f5bf32c 100644
--- a/include/grpc/support/avl.h
+++ b/include/grpc/support/avl.h
@@ -88,5 +88,10 @@
     does not mutate avl.
     returns NULL if key is not found. */
 GPRAPI void *gpr_avl_get(gpr_avl avl, void *key);
+/** Return 1 if avl contains key, 0 otherwise; if it has the key, sets *value to
+    its value*/
+GPRAPI int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value);
+/** Return 1 if avl is empty, 0 otherwise */
+GPRAPI int gpr_avl_is_empty(gpr_avl avl);
 
 #endif /* GRPC_SUPPORT_AVL_H */
diff --git a/package.xml b/package.xml
index b25e42c..67e9bb2 100644
--- a/package.xml
+++ b/package.xml
@@ -96,7 +96,6 @@
     <file baseinstalldir="/" name="src/core/lib/support/backoff.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/block_annotate.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/support/load_file.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
@@ -119,7 +118,6 @@
     <file baseinstalldir="/" name="src/core/lib/support/env_windows.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/histogram.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/host_port.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/support/load_file.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/log.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/log_android.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/log_linux.c" role="src" />
@@ -197,6 +195,7 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/closure.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
@@ -206,6 +205,7 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/load_file.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/pollset.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set.h" role="src" />
@@ -293,6 +293,7 @@
     <file baseinstalldir="/" name="src/core/lib/security/transport/handshake.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/util/b64.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.h" role="src" />
@@ -349,6 +350,7 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/error.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.c" role="src" />
@@ -358,6 +360,7 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_windows.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/load_file.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set_windows.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/pollset_windows.c" role="src" />
@@ -460,6 +463,7 @@
     <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
index 86ec2ae..72e4e54 100644
--- a/src/core/ext/census/grpc_filter.c
+++ b/src/core/ext/census/grpc_filter.c
@@ -91,14 +91,14 @@
 }
 
 static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
-                                bool success) {
+                                grpc_error *error) {
   grpc_call_element *elem = ptr;
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
   }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
 }
 
 static void server_mutate_op(grpc_call_element *elem,
diff --git a/src/core/ext/client_config/channel_connectivity.c b/src/core/ext/client_config/channel_connectivity.c
index cc60f24..20c01a9 100644
--- a/src/core/ext/client_config/channel_connectivity.c
+++ b/src/core/ext/client_config/channel_connectivity.c
@@ -75,7 +75,6 @@
 typedef struct {
   gpr_mu mu;
   callback_phase phase;
-  int success;
   grpc_closure on_complete;
   grpc_timer alarm;
   grpc_connectivity_state state;
@@ -122,7 +121,7 @@
 }
 
 static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
-                        int due_to_completion) {
+                        bool due_to_completion, grpc_error *error) {
   int delete = 0;
 
   if (due_to_completion) {
@@ -130,14 +129,26 @@
   }
 
   gpr_mu_lock(&w->mu);
+
   if (due_to_completion) {
-    w->success = 1;
+    if (grpc_trace_operation_failures) {
+      GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
+    }
+    GRPC_ERROR_UNREF(error);
+    error = GRPC_ERROR_NONE;
+  } else {
+    if (error == GRPC_ERROR_NONE) {
+      error =
+          GRPC_ERROR_CREATE("Timed out waiting for connection state change");
+    } else if (error == GRPC_ERROR_CANCELLED) {
+      error = GRPC_ERROR_NONE;
+    }
   }
   switch (w->phase) {
     case WAITING:
       w->phase = CALLING_BACK;
-      grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->success, finished_completion,
-                     w, &w->completion_storage);
+      grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error),
+                     finished_completion, w, &w->completion_storage);
       break;
     case CALLING_BACK:
       w->phase = CALLING_BACK_AND_FINISHED;
@@ -153,14 +164,18 @@
   if (delete) {
     delete_state_watcher(exec_ctx, w);
   }
+
+  GRPC_ERROR_UNREF(error);
 }
 
-static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
-  partly_done(exec_ctx, pw, 1);
+static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw,
+                           grpc_error *error) {
+  partly_done(exec_ctx, pw, true, GRPC_ERROR_REF(error));
 }
 
-static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
-  partly_done(exec_ctx, pw, 0);
+static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw,
+                             grpc_error *error) {
+  partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error));
 }
 
 void grpc_channel_watch_connectivity_state(
@@ -185,7 +200,6 @@
   grpc_closure_init(&w->on_complete, watch_complete, w);
   w->phase = WAITING;
   w->state = last_observed_state;
-  w->success = 0;
   w->cq = cq;
   w->tag = tag;
   w->channel = channel;
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index e297dfa..1d5a7d5 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -117,6 +117,7 @@
 static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
                                                   channel_data *chand,
                                                   grpc_connectivity_state state,
+                                                  grpc_error *error,
                                                   const char *reason) {
   if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
        state == GRPC_CHANNEL_SHUTDOWN) &&
@@ -127,11 +128,13 @@
         /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
         /* check= */ 0);
   }
-  grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, reason);
+  grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
+                              reason);
 }
 
-static void on_lb_policy_state_changed_locked(
-    grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
+static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
+                                              lb_policy_connectivity_watcher *w,
+                                              grpc_error *error) {
   grpc_connectivity_state publish_state = w->state;
   /* check if the notification is for a stale policy */
   if (w->lb_policy != w->chand->lb_policy) return;
@@ -143,18 +146,18 @@
     w->chand->lb_policy = NULL;
   }
   set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
-                                        "lb_changed");
+                                        GRPC_ERROR_REF(error), "lb_changed");
   if (w->state != GRPC_CHANNEL_SHUTDOWN) {
     watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
   }
 }
 
 static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                       bool iomgr_success) {
+                                       grpc_error *error) {
   lb_policy_connectivity_watcher *w = arg;
 
   gpr_mu_lock(&w->chand->mu_config);
-  on_lb_policy_state_changed_locked(exec_ctx, w);
+  on_lb_policy_state_changed_locked(exec_ctx, w, error);
   gpr_mu_unlock(&w->chand->mu_config);
 
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
@@ -176,19 +179,22 @@
 }
 
 static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                 bool iomgr_success) {
+                                 grpc_error *error) {
   channel_data *chand = arg;
   grpc_lb_policy *lb_policy = NULL;
   grpc_lb_policy *old_lb_policy;
   grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
   int exit_idle = 0;
+  grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
 
   if (chand->incoming_configuration != NULL) {
     lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
     if (lb_policy != NULL) {
       GRPC_LB_POLICY_REF(lb_policy, "channel");
       GRPC_LB_POLICY_REF(lb_policy, "config_change");
-      state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
+      GRPC_ERROR_UNREF(state_error);
+      state =
+          grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
     }
 
     grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
@@ -208,7 +214,9 @@
     grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
                                NULL);
   } else if (chand->resolver == NULL /* disconnected */) {
-    grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
+    grpc_closure_list_fail_all(
+        &chand->waiting_for_config_closures,
+        GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
     grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
                                NULL);
   }
@@ -218,9 +226,9 @@
     chand->exit_idle_when_lb_policy_arrives = 0;
   }
 
-  if (iomgr_success && chand->resolver) {
-    set_channel_connectivity_state_locked(exec_ctx, chand, state,
-                                          "new_lb+resolver");
+  if (error == GRPC_ERROR_NONE && chand->resolver) {
+    set_channel_connectivity_state_locked(
+        exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
     if (lb_policy != NULL) {
       watch_lb_policy(exec_ctx, chand, lb_policy, state);
     }
@@ -235,8 +243,12 @@
       GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
       chand->resolver = NULL;
     }
+    grpc_error *refs[] = {error, state_error};
     set_channel_connectivity_state_locked(
-        exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, "resolver_gone");
+        exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
+        GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
+                                      GPR_ARRAY_SIZE(refs)),
+        "resolver_gone");
     gpr_mu_unlock(&chand->mu_config);
   }
 
@@ -256,6 +268,7 @@
   }
 
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
+  GRPC_ERROR_UNREF(state_error);
 }
 
 static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
@@ -263,7 +276,7 @@
                                   grpc_transport_op *op) {
   channel_data *chand = elem->channel_data;
 
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
 
   GPR_ASSERT(op->set_accept_stream == false);
   if (op->bind_pollset != NULL) {
@@ -282,7 +295,9 @@
 
   if (op->send_ping != NULL) {
     if (chand->lb_policy == NULL) {
-      grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, op->send_ping,
+                          GRPC_ERROR_CREATE("Ping with no load balancing"),
+                          NULL);
     } else {
       grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
       op->bind_pollset = NULL;
@@ -290,24 +305,29 @@
     op->send_ping = NULL;
   }
 
-  if (op->disconnect && chand->resolver != NULL) {
-    set_channel_connectivity_state_locked(exec_ctx, chand,
-                                          GRPC_CHANNEL_SHUTDOWN, "disconnect");
-    grpc_resolver_shutdown(exec_ctx, chand->resolver);
-    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
-    chand->resolver = NULL;
-    if (!chand->started_resolving) {
-      grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
-      grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
-                                 NULL);
+  if (op->disconnect_with_error != GRPC_ERROR_NONE) {
+    if (chand->resolver != NULL) {
+      set_channel_connectivity_state_locked(
+          exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
+          GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
+      grpc_resolver_shutdown(exec_ctx, chand->resolver);
+      GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+      chand->resolver = NULL;
+      if (!chand->started_resolving) {
+        grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
+                                   GRPC_ERROR_REF(op->disconnect_with_error));
+        grpc_exec_ctx_enqueue_list(exec_ctx,
+                                   &chand->waiting_for_config_closures, NULL);
+      }
+      if (chand->lb_policy != NULL) {
+        grpc_pollset_set_del_pollset_set(exec_ctx,
+                                         chand->lb_policy->interested_parties,
+                                         chand->interested_parties);
+        GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
+        chand->lb_policy = NULL;
+      }
     }
-    if (chand->lb_policy != NULL) {
-      grpc_pollset_set_del_pollset_set(exec_ctx,
-                                       chand->lb_policy->interested_parties,
-                                       chand->interested_parties);
-      GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
-      chand->lb_policy = NULL;
-    }
+    GRPC_ERROR_UNREF(op->disconnect_with_error);
   }
   gpr_mu_unlock(&chand->mu_config);
 }
@@ -327,16 +347,17 @@
                               grpc_connected_subchannel **connected_subchannel,
                               grpc_closure *on_ready);
 
-static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
+                             grpc_error *error) {
   continue_picking_args *cpa = arg;
   if (cpa->connected_subchannel == NULL) {
     /* cancelled, do nothing */
-  } else if (!success) {
-    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
+  } else if (error != GRPC_ERROR_NONE) {
+    grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
   } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
                                 cpa->initial_metadata_flags,
                                 cpa->connected_subchannel, cpa->on_ready)) {
-    grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
   }
   gpr_free(cpa);
 }
@@ -361,11 +382,12 @@
                                  connected_subchannel);
     }
     for (closure = chand->waiting_for_config_closures.head; closure != NULL;
-         closure = grpc_closure_next(closure)) {
+         closure = closure->next_data.next) {
       cpa = closure->cb_arg;
       if (cpa->connected_subchannel == connected_subchannel) {
         cpa->connected_subchannel = NULL;
-        grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
+        grpc_exec_ctx_sched(exec_ctx, cpa->on_ready,
+                            GRPC_ERROR_CREATE("Pick cancelled"), NULL);
       }
     }
     gpr_mu_unlock(&chand->mu_config);
@@ -397,10 +419,11 @@
     cpa->on_ready = on_ready;
     cpa->elem = elem;
     grpc_closure_init(&cpa->closure, continue_picking, cpa);
-    grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure,
-                          1);
+    grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
+                             GRPC_ERROR_NONE);
   } else {
-    grpc_exec_ctx_enqueue(exec_ctx, on_ready, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
+                        NULL);
   }
   gpr_mu_unlock(&chand->mu_config);
   return 0;
@@ -507,7 +530,7 @@
   channel_data *chand = elem->channel_data;
   grpc_connectivity_state out;
   gpr_mu_lock(&chand->mu_config);
-  out = grpc_connectivity_state_check(&chand->state_tracker);
+  out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
   if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
     if (chand->lb_policy != NULL) {
       grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
@@ -534,7 +557,7 @@
 } external_connectivity_watcher;
 
 static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
-                                       bool iomgr_success) {
+                                       grpc_error *error) {
   external_connectivity_watcher *w = arg;
   grpc_closure *follow_up = w->on_complete;
   grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
@@ -542,7 +565,7 @@
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
                            "external_connectivity_watcher");
   gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
+  follow_up->cb(exec_ctx, follow_up->cb_arg, error);
 }
 
 void grpc_client_channel_watch_connectivity_state(
diff --git a/src/core/ext/client_config/connector.h b/src/core/ext/client_config/connector.h
index dd85dfc..ea9d237 100644
--- a/src/core/ext/client_config/connector.h
+++ b/src/core/ext/client_config/connector.h
@@ -64,7 +64,7 @@
   grpc_transport *transport;
 
   /** channel arguments (to be passed to the filters) */
-  const grpc_channel_args *channel_args;
+  grpc_channel_args *channel_args;
 } grpc_connect_out_args;
 
 struct grpc_connector_vtable {
diff --git a/src/core/ext/client_config/lb_policy.c b/src/core/ext/client_config/lb_policy.c
index dc16124..8b980b2 100644
--- a/src/core/ext/client_config/lb_policy.c
+++ b/src/core/ext/client_config/lb_policy.c
@@ -139,6 +139,8 @@
 }
 
 grpc_connectivity_state grpc_lb_policy_check_connectivity(
-    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
-  return policy->vtable->check_connectivity(exec_ctx, policy);
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+    grpc_error **connectivity_error) {
+  return policy->vtable->check_connectivity(exec_ctx, policy,
+                                            connectivity_error);
 }
diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h
index 56fa111..3cfd041 100644
--- a/src/core/ext/client_config/lb_policy.h
+++ b/src/core/ext/client_config/lb_policy.h
@@ -77,8 +77,9 @@
   void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
 
   /** check the current connectivity of the lb_policy */
-  grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
-                                                grpc_lb_policy *policy);
+  grpc_connectivity_state (*check_connectivity)(
+      grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+      grpc_error **connectivity_error);
 
   /** call notify when the connectivity state of a channel changes from *state.
       Updates *state with the new state of the policy */
@@ -154,6 +155,7 @@
                                            grpc_closure *closure);
 
 grpc_connectivity_state grpc_lb_policy_check_connectivity(
-    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+    grpc_error **connectivity_error);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_H */
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index 85183b0..468067e 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -54,7 +54,7 @@
 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
 
 #define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
-#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2
+#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
@@ -147,7 +147,7 @@
   (((grpc_subchannel_call *)(callstack)) - 1)
 
 static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
-                                 bool iomgr_success);
+                                 grpc_error *error);
 
 #ifdef GRPC_STREAM_REFCOUNT_DEBUG
 #define REF_REASON reason
@@ -177,7 +177,7 @@
  */
 
 static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
+                               grpc_error *error) {
   grpc_connected_subchannel *c = arg;
   grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
   gpr_free(c);
@@ -200,7 +200,7 @@
  */
 
 static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
+                               grpc_error *error) {
   grpc_subchannel *c = arg;
   gpr_free((void *)c->filters);
   grpc_channel_args_destroy(c->args);
@@ -290,8 +290,8 @@
   gpr_atm old_refs;
   old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
   if (old_refs == 1) {
-    grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(subchannel_destroy, c),
-                          true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(subchannel_destroy, c),
+                        GRPC_ERROR_NONE, NULL);
   }
 }
 
@@ -382,7 +382,8 @@
   args.initial_connect_string = c->initial_connect_string;
 
   grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                              GRPC_CHANNEL_CONNECTING, "state_change");
+                              GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
+                              "state_change");
   grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
                          &c->connected);
 }
@@ -393,16 +394,17 @@
   continue_connect(exec_ctx, c);
 }
 
-grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
+grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
+                                                           grpc_error **error) {
   grpc_connectivity_state state;
   gpr_mu_lock(&c->mu);
-  state = grpc_connectivity_state_check(&c->state_tracker);
+  state = grpc_connectivity_state_check(&c->state_tracker, error);
   gpr_mu_unlock(&c->mu);
   return state;
 }
 
 static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
+                                           grpc_error *error) {
   external_state_watcher *w = arg;
   grpc_closure *follow_up = w->notify;
   if (w->pollset_set != NULL) {
@@ -415,7 +417,7 @@
   gpr_mu_unlock(&w->subchannel->mu);
   GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
   gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, success);
+  follow_up->cb(exec_ctx, follow_up->cb_arg, error);
 }
 
 void grpc_subchannel_notify_on_state_change(
@@ -469,7 +471,7 @@
 }
 
 static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
-                                              bool iomgr_success) {
+                                              grpc_error *error) {
   state_watcher *sw = p;
   grpc_subchannel *c = sw->subchannel;
   gpr_mu *mu = &c->mu;
@@ -477,20 +479,19 @@
   gpr_mu_lock(mu);
 
   /* if we failed just leave this closure */
-  if (iomgr_success) {
-    if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-      /* any errors on a subchannel ==> we're done, create a new one */
-      sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
-    }
-    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                                sw->connectivity_state, "reflect_child");
-    if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
-      grpc_connected_subchannel_notify_on_state_change(
-          exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
-          &sw->connectivity_state, &sw->closure);
-      GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
-      sw = NULL;
-    }
+  if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    /* any errors on a subchannel ==> we're done, create a new one */
+    sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
+  }
+  grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
+                              sw->connectivity_state, GRPC_ERROR_REF(error),
+                              "reflect_child");
+  if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
+    grpc_connected_subchannel_notify_on_state_change(
+        exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
+        &sw->connectivity_state, &sw->closure);
+    GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
+    sw = NULL;
   }
 
   gpr_mu_unlock(mu);
@@ -592,17 +593,20 @@
 
   /* signal completion */
   grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
-                              "connected");
+                              GRPC_ERROR_NONE, "connected");
 }
 
-static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
+static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_subchannel *c = arg;
   gpr_mu_lock(&c->mu);
   c->have_alarm = 0;
   if (c->disconnected) {
-    iomgr_success = 0;
+    error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
+  } else {
+    GRPC_ERROR_REF(error);
   }
-  if (iomgr_success) {
+  if (error == GRPC_ERROR_NONE) {
+    gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
     c->next_attempt =
         gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
     continue_connect(exec_ctx, c);
@@ -611,11 +615,13 @@
     gpr_mu_unlock(&c->mu);
     GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
-                                 bool iomgr_success) {
+                                 grpc_error *error) {
   grpc_subchannel *c = arg;
+  grpc_channel_args *delete_channel_args = c->connecting_result.channel_args;
 
   GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
   gpr_mu_lock(&c->mu);
@@ -627,13 +633,26 @@
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     GPR_ASSERT(!c->have_alarm);
     c->have_alarm = 1;
-    grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
-                                GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                "connect_failed");
+    grpc_connectivity_state_set(
+        exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
+        GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1),
+        "connect_failed");
+    gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
+    const char *errmsg = grpc_error_string(error);
+    gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
+    if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
+        0) {
+      gpr_log(GPR_INFO, "Retry immediately");
+    } else {
+      gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
+              time_til_next.tv_sec, time_til_next.tv_nsec);
+    }
     grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
+    grpc_error_free_string(errmsg);
   }
   gpr_mu_unlock(&c->mu);
   GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
+  grpc_channel_args_destroy(delete_channel_args);
 }
 
 /*
@@ -641,7 +660,7 @@
  */
 
 static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
-                                    bool success) {
+                                    grpc_error *error) {
   grpc_subchannel_call *c = call;
   GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
   grpc_connected_subchannel *connection = c->connection;
diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h
index 525f854..b6d39f5 100644
--- a/src/core/ext/client_config/subchannel.h
+++ b/src/core/ext/client_config/subchannel.h
@@ -119,7 +119,7 @@
 
 /** poll the current connectivity state of a channel */
 grpc_connectivity_state grpc_subchannel_check_connectivity(
-    grpc_subchannel *channel);
+    grpc_subchannel *channel, grpc_error **error);
 
 /** call notify when the connectivity state of a channel changes from *state.
     Updates *state with the new state of the channel */
diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c
index 3df1f25..e31800e 100644
--- a/src/core/ext/client_config/subchannel_call_holder.c
+++ b/src/core/ext/client_config/subchannel_call_holder.c
@@ -43,14 +43,14 @@
 #define CANCELLED_CALL ((grpc_subchannel_call *)1)
 
 static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *holder,
-                             bool success);
+                             grpc_error *error);
 static void retry_ops(grpc_exec_ctx *exec_ctx, void *retry_ops_args,
-                      bool success);
+                      grpc_error *error);
 
 static void add_waiting_locked(grpc_subchannel_call_holder *holder,
                                grpc_transport_stream_op *op);
 static void fail_locked(grpc_exec_ctx *exec_ctx,
-                        grpc_subchannel_call_holder *holder);
+                        grpc_subchannel_call_holder *holder, grpc_error *error);
 static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
                                  grpc_subchannel_call_holder *holder);
 
@@ -91,7 +91,8 @@
   grpc_subchannel_call *call = GET_CALL(holder);
   GPR_TIMER_BEGIN("grpc_subchannel_call_holder_perform_op", 0);
   if (call == CANCELLED_CALL) {
-    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
+                                                 GRPC_ERROR_CANCELLED);
     GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
     return;
   }
@@ -107,7 +108,8 @@
   call = GET_CALL(holder);
   if (call == CANCELLED_CALL) {
     gpr_mu_unlock(&holder->mu);
-    grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
+                                                 GRPC_ERROR_CANCELLED);
     GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
     return;
   }
@@ -124,7 +126,10 @@
     } else {
       switch (holder->creation_phase) {
         case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
-          fail_locked(exec_ctx, holder);
+          fail_locked(exec_ctx, holder,
+                      grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
+                                         GRPC_ERROR_INT_GRPC_STATUS,
+                                         op->cancel_with_status));
           break;
         case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
           holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
@@ -132,7 +137,8 @@
           break;
       }
       gpr_mu_unlock(&holder->mu);
-      grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
+                                                   GRPC_ERROR_CANCELLED);
       GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
       return;
     }
@@ -168,7 +174,8 @@
   GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
 }
 
-static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
+                             grpc_error *error) {
   grpc_subchannel_call_holder *holder = arg;
   gpr_mu_lock(&holder->mu);
   GPR_ASSERT(holder->creation_phase ==
@@ -176,10 +183,14 @@
   holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
   if (holder->connected_subchannel == NULL) {
     gpr_atm_no_barrier_store(&holder->subchannel_call, 1);
-    fail_locked(exec_ctx, holder);
+    fail_locked(exec_ctx, holder,
+                GRPC_ERROR_CREATE_REFERENCING("Failed to create subchannel",
+                                              &error, 1));
   } else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
     /* already cancelled before subchannel became ready */
-    fail_locked(exec_ctx, holder);
+    fail_locked(exec_ctx, holder,
+                GRPC_ERROR_CREATE_REFERENCING(
+                    "Cancelled before creating subchannel", &error, 1));
   } else {
     gpr_atm_rel_store(
         &holder->subchannel_call,
@@ -205,18 +216,18 @@
   a->call = GET_CALL(holder);
   if (a->call == CANCELLED_CALL) {
     gpr_free(a);
-    fail_locked(exec_ctx, holder);
+    fail_locked(exec_ctx, holder, GRPC_ERROR_CANCELLED);
     return;
   }
   holder->waiting_ops = NULL;
   holder->waiting_ops_count = 0;
   holder->waiting_ops_capacity = 0;
   GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
-  grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(retry_ops, a), true,
-                        NULL);
+  grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(retry_ops, a),
+                      GRPC_ERROR_NONE, NULL);
 }
 
-static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, bool success) {
+static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
   retry_ops_args *a = args;
   size_t i;
   for (i = 0; i < a->nops; i++) {
@@ -241,13 +252,15 @@
 }
 
 static void fail_locked(grpc_exec_ctx *exec_ctx,
-                        grpc_subchannel_call_holder *holder) {
+                        grpc_subchannel_call_holder *holder,
+                        grpc_error *error) {
   size_t i;
   for (i = 0; i < holder->waiting_ops_count; i++) {
-    grpc_transport_stream_op_finish_with_failure(exec_ctx,
-                                                 &holder->waiting_ops[i]);
+    grpc_transport_stream_op_finish_with_failure(
+        exec_ctx, &holder->waiting_ops[i], GRPC_ERROR_REF(error));
   }
   holder->waiting_ops_count = 0;
+  GRPC_ERROR_UNREF(error);
 }
 
 char *grpc_subchannel_call_holder_get_peer(
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index cc559eb..9decf70 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -103,8 +103,9 @@
   p->shutdown = 1;
   pp = p->pending_picks;
   p->pending_picks = NULL;
-  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                              GRPC_CHANNEL_SHUTDOWN, "shutdown");
+  grpc_connectivity_state_set(
+      exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
+      GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
   /* cancel subscription */
   if (selected != NULL) {
     grpc_connected_subchannel_notify_on_state_change(
@@ -120,7 +121,7 @@
     *pp->target = NULL;
     grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                              p->base.interested_parties);
-    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
     gpr_free(pp);
     pp = next;
   }
@@ -139,7 +140,8 @@
       grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                p->base.interested_parties);
       *target = NULL;
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
+                          GRPC_ERROR_CREATE("Pick Cancelled"), NULL);
       gpr_free(pp);
     } else {
       pp->next = p->pending_picks;
@@ -164,7 +166,8 @@
         initial_metadata_flags_eq) {
       grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                p->base.interested_parties);
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
+                          GRPC_ERROR_CREATE("Pick Cancelled"), NULL);
       gpr_free(pp);
     } else {
       pp->next = p->pending_picks;
@@ -237,7 +240,7 @@
 }
 
 static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
-                                bool iomgr_success) {
+                                grpc_error *error) {
   pick_first_lb_policy *p = arg;
   size_t i;
   size_t num_subchannels = p->num_subchannels;
@@ -258,12 +261,14 @@
 }
 
 static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    bool iomgr_success) {
+                                    grpc_error *error) {
   pick_first_lb_policy *p = arg;
   grpc_subchannel *selected_subchannel;
   pending_pick *pp;
   grpc_connected_subchannel *selected;
 
+  GRPC_ERROR_REF(error);
+
   gpr_mu_lock(&p->mu);
 
   selected = GET_SELECTED(p);
@@ -271,6 +276,7 @@
   if (p->shutdown) {
     gpr_mu_unlock(&p->mu);
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
+    GRPC_ERROR_UNREF(error);
     return;
   } else if (selected != NULL) {
     if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@@ -278,7 +284,8 @@
       p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
     }
     grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                p->checking_connectivity, "selected_changed");
+                                p->checking_connectivity, GRPC_ERROR_REF(error),
+                                "selected_changed");
     if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
       grpc_connected_subchannel_notify_on_state_change(
           exec_ctx, selected, p->base.interested_parties,
@@ -291,7 +298,8 @@
     switch (p->checking_connectivity) {
       case GRPC_CHANNEL_READY:
         grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_READY, "connecting_ready");
+                                    GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
+                                    "connecting_ready");
         selected_subchannel = p->subchannels[p->checking_subchannel];
         selected =
             grpc_subchannel_get_connected_subchannel(selected_subchannel);
@@ -300,15 +308,16 @@
         /* drop the pick list: we are connected now */
         GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
         gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
-        grpc_exec_ctx_enqueue(
-            exec_ctx, grpc_closure_create(destroy_subchannels, p), true, NULL);
+        grpc_exec_ctx_sched(exec_ctx,
+                            grpc_closure_create(destroy_subchannels, p),
+                            GRPC_ERROR_NONE, NULL);
         /* update any calls that were waiting for a pick */
         while ((pp = p->pending_picks)) {
           p->pending_picks = pp->next;
           *pp->target = selected;
           grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                    p->base.interested_parties);
-          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+          grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
           gpr_free(pp);
         }
         grpc_connected_subchannel_notify_on_state_change(
@@ -320,12 +329,13 @@
             (p->checking_subchannel + 1) % p->num_subchannels;
         if (p->checking_subchannel == 0) {
           /* only trigger transient failure when we've tried all alternatives */
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                      "connecting_transient_failure");
+          grpc_connectivity_state_set(
+              exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
+              GRPC_ERROR_REF(error), "connecting_transient_failure");
         }
+        GRPC_ERROR_UNREF(error);
         p->checking_connectivity = grpc_subchannel_check_connectivity(
-            p->subchannels[p->checking_subchannel]);
+            p->subchannels[p->checking_subchannel], &error);
         if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
           grpc_subchannel_notify_on_state_change(
               exec_ctx, p->subchannels[p->checking_subchannel],
@@ -337,9 +347,9 @@
         break;
       case GRPC_CHANNEL_CONNECTING:
       case GRPC_CHANNEL_IDLE:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_CONNECTING,
-                                    "connecting_changed");
+        grpc_connectivity_state_set(
+            exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING,
+            GRPC_ERROR_REF(error), "connecting_changed");
         grpc_subchannel_notify_on_state_change(
             exec_ctx, p->subchannels[p->checking_subchannel],
             p->base.interested_parties, &p->checking_connectivity,
@@ -352,38 +362,45 @@
         GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
                               "pick_first");
         if (p->num_subchannels == 0) {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_SHUTDOWN,
-                                      "no_more_channels");
+          grpc_connectivity_state_set(
+              exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
+              GRPC_ERROR_CREATE_REFERENCING("Pick first exhausted channels",
+                                            &error, 1),
+              "no_more_channels");
           while ((pp = p->pending_picks)) {
             p->pending_picks = pp->next;
             *pp->target = NULL;
-            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+            grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE,
+                                NULL);
             gpr_free(pp);
           }
           GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
                                     "pick_first_connectivity");
         } else {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                      "subchannel_failed");
+          grpc_connectivity_state_set(
+              exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
+              GRPC_ERROR_REF(error), "subchannel_failed");
           p->checking_subchannel %= p->num_subchannels;
+          GRPC_ERROR_UNREF(error);
           p->checking_connectivity = grpc_subchannel_check_connectivity(
-              p->subchannels[p->checking_subchannel]);
+              p->subchannels[p->checking_subchannel], &error);
           goto loop;
         }
     }
   }
 
   gpr_mu_unlock(&p->mu);
+
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol) {
+                                                     grpc_lb_policy *pol,
+                                                     grpc_error **error) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
   grpc_connectivity_state st;
   gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker);
+  st = grpc_connectivity_state_check(&p->state_tracker, error);
   gpr_mu_unlock(&p->mu);
   return st;
 }
@@ -406,7 +423,8 @@
   if (selected) {
     grpc_connected_subchannel_ping(exec_ctx, selected, closure);
   } else {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"),
+                        NULL);
   }
 }
 
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index 40dd7c5..7bcf608 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -265,11 +265,13 @@
   while ((pp = p->pending_picks)) {
     p->pending_picks = pp->next;
     *pp->target = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
+                        GRPC_ERROR_CREATE("Channel Shutdown"), NULL);
     gpr_free(pp);
   }
-  grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                              GRPC_CHANNEL_SHUTDOWN, "shutdown");
+  grpc_connectivity_state_set(
+      exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
+      GRPC_ERROR_CREATE("Channel Shutdown"), "shutdown");
   for (i = 0; i < p->num_subchannels; i++) {
     subchannel_data *sd = p->subchannels[i];
     grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
@@ -291,7 +293,8 @@
       grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                p->base.interested_parties);
       *target = NULL;
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CANCELLED,
+                          NULL);
       gpr_free(pp);
     } else {
       pp->next = p->pending_picks;
@@ -317,7 +320,8 @@
       grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                p->base.interested_parties);
       *pp->target = NULL;
-      grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CANCELLED,
+                          NULL);
       gpr_free(pp);
     } else {
       pp->next = p->pending_picks;
@@ -396,7 +400,7 @@
 }
 
 static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    bool iomgr_success) {
+                                    grpc_error *error) {
   subchannel_data *sd = arg;
   round_robin_lb_policy *p = sd->policy;
   pending_pick *pp;
@@ -404,6 +408,7 @@
 
   int unref = 0;
 
+  GRPC_ERROR_REF(error);
   gpr_mu_lock(&p->mu);
 
   if (p->shutdown) {
@@ -412,7 +417,8 @@
     switch (sd->connectivity_state) {
       case GRPC_CHANNEL_READY:
         grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_READY, "connecting_ready");
+                                    GRPC_CHANNEL_READY, GRPC_ERROR_REF(error),
+                                    "connecting_ready");
         /* add the newly connected subchannel to the list of connected ones.
          * Note that it goes to the "end of the line". */
         sd->ready_list_node = add_connected_sc_locked(p, sd->subchannel);
@@ -436,7 +442,7 @@
           }
           grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
                                                    p->base.interested_parties);
-          grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+          grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
           gpr_free(pp);
         }
         grpc_subchannel_notify_on_state_change(
@@ -445,9 +451,9 @@
         break;
       case GRPC_CHANNEL_CONNECTING:
       case GRPC_CHANNEL_IDLE:
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    sd->connectivity_state,
-                                    "connecting_changed");
+        grpc_connectivity_state_set(
+            exec_ctx, &p->state_tracker, sd->connectivity_state,
+            GRPC_ERROR_REF(error), "connecting_changed");
         grpc_subchannel_notify_on_state_change(
             exec_ctx, sd->subchannel, p->base.interested_parties,
             &sd->connectivity_state, &sd->connectivity_changed_closure);
@@ -463,9 +469,9 @@
           remove_disconnected_sc_locked(p, sd->ready_list_node);
           sd->ready_list_node = NULL;
         }
-        grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                    GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                    "connecting_transient_failure");
+        grpc_connectivity_state_set(
+            exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
+            GRPC_ERROR_REF(error), "connecting_transient_failure");
         break;
       case GRPC_CHANNEL_SHUTDOWN:
         if (sd->ready_list_node != NULL) {
@@ -482,19 +488,22 @@
 
         unref = 1;
         if (p->num_subchannels == 0) {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_SHUTDOWN,
-                                      "no_more_channels");
+          grpc_connectivity_state_set(
+              exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
+              GRPC_ERROR_CREATE_REFERENCING("Round Robin Channels Exhausted",
+                                            &error, 1),
+              "no_more_channels");
           while ((pp = p->pending_picks)) {
             p->pending_picks = pp->next;
             *pp->target = NULL;
-            grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
+            grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE,
+                                NULL);
             gpr_free(pp);
           }
         } else {
-          grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
-                                      GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                      "subchannel_failed");
+          grpc_connectivity_state_set(
+              exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
+              GRPC_ERROR_REF(error), "subchannel_failed");
         }
     } /* switch */
   }   /* !unref */
@@ -504,14 +513,17 @@
   if (unref) {
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
   }
+
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol) {
+                                                     grpc_lb_policy *pol,
+                                                     grpc_error **error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   grpc_connectivity_state st;
   gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker);
+  st = grpc_connectivity_state_check(&p->state_tracker, error);
   gpr_mu_unlock(&p->mu);
   return st;
 }
@@ -539,7 +551,8 @@
     grpc_connected_subchannel_ping(exec_ctx, target, closure);
   } else {
     gpr_mu_unlock(&p->mu);
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure,
+                        GRPC_ERROR_CREATE("Round Robin not connected"), NULL);
   }
 }
 
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 5efc95e..31ac968 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -82,6 +82,9 @@
   grpc_timer retry_timer;
   /** retry backoff state */
   gpr_backoff backoff_state;
+
+  /** currently resolving addresses */
+  grpc_resolved_addresses *addresses;
 } dns_resolver;
 
 static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@@ -108,7 +111,8 @@
   }
   if (r->next_completion != NULL) {
     *r->target_config = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, r->next_completion,
+                        GRPC_ERROR_CREATE("Resolver Shutdown"), NULL);
     r->next_completion = NULL;
   }
   gpr_mu_unlock(&r->mu);
@@ -143,12 +147,12 @@
 }
 
 static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
-                               bool success) {
+                               grpc_error *error) {
   dns_resolver *r = arg;
 
   gpr_mu_lock(&r->mu);
   r->have_retry_timer = false;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     if (!r->resolving) {
       dns_start_resolving_locked(exec_ctx, r);
     }
@@ -159,13 +163,14 @@
 }
 
 static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                            grpc_resolved_addresses *addresses) {
+                            grpc_error *error) {
   dns_resolver *r = arg;
   grpc_client_config *config = NULL;
   grpc_lb_policy *lb_policy;
   gpr_mu_lock(&r->mu);
   GPR_ASSERT(r->resolving);
   r->resolving = 0;
+  grpc_resolved_addresses *addresses = r->addresses;
   if (addresses != NULL) {
     grpc_lb_policy_args lb_policy_args;
     config = grpc_client_config_create();
@@ -183,12 +188,18 @@
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
     gpr_timespec timeout = gpr_time_sub(next_try, now);
-    gpr_log(GPR_DEBUG,
-            "dns resolution failed: retrying in %" PRId64 ".%09d seconds",
-            timeout.tv_sec, timeout.tv_nsec);
+    const char *msg = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
+    grpc_error_free_string(msg);
     GPR_ASSERT(!r->have_retry_timer);
     r->have_retry_timer = true;
     GRPC_RESOLVER_REF(&r->base, "retry-timer");
+    if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) <= 0) {
+      gpr_log(GPR_DEBUG, "retrying in %" PRId64 ".%09d seconds", timeout.tv_sec,
+              timeout.tv_nsec);
+    } else {
+      gpr_log(GPR_DEBUG, "retrying immediately");
+    }
     grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
                     now);
   }
@@ -208,7 +219,9 @@
   GRPC_RESOLVER_REF(&r->base, "dns-resolving");
   GPR_ASSERT(!r->resolving);
   r->resolving = 1;
-  grpc_resolve_address(exec_ctx, r->name, r->default_port, dns_on_resolved, r);
+  r->addresses = NULL;
+  grpc_resolve_address(exec_ctx, r->name, r->default_port,
+                       grpc_closure_create(dns_on_resolved, r), &r->addresses);
 }
 
 static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -219,7 +232,7 @@
     if (r->resolved_config) {
       grpc_client_config_ref(r->resolved_config);
     }
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
     r->published_version = r->resolved_version;
   }
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index a4fa9ac..1f7cce2 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -92,7 +92,7 @@
   gpr_mu_lock(&r->mu);
   if (r->next_completion != NULL) {
     *r->target_config = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
   }
   gpr_mu_unlock(&r->mu);
@@ -133,7 +133,7 @@
     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
     r->published = 1;
     *r->target_config = cfg;
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
   }
 }
diff --git a/src/core/ext/resolver/zookeeper/zookeeper_resolver.c b/src/core/ext/resolver/zookeeper/zookeeper_resolver.c
deleted file mode 100644
index deb4b9b..0000000
--- a/src/core/ext/resolver/zookeeper/zookeeper_resolver.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-
-#include <grpc/grpc_zookeeper.h>
-#include <zookeeper/zookeeper.h>
-
-#include "src/core/ext/client_config/lb_policy_registry.h"
-#include "src/core/ext/client_config/resolver_registry.h"
-#include "src/core/lib/iomgr/resolve_address.h"
-#include "src/core/lib/json/json.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/surface/api_trace.h"
-
-/** Zookeeper session expiration time in milliseconds */
-#define GRPC_ZOOKEEPER_SESSION_TIMEOUT 15000
-
-typedef struct {
-  /** base class: must be first */
-  grpc_resolver base;
-  /** refcount */
-  gpr_refcount refs;
-  /** name to resolve */
-  char *name;
-  /** subchannel factory */
-  grpc_client_channel_factory *client_channel_factory;
-  /** load balancing policy name */
-  char *lb_policy_name;
-
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
-  /** are we currently resolving? */
-  int resolving;
-  /** which version of resolved_config have we published? */
-  int published_version;
-  /** which version of resolved_config is current? */
-  int resolved_version;
-  /** pending next completion, or NULL */
-  grpc_closure *next_completion;
-  /** target config address for next completion */
-  grpc_client_config **target_config;
-  /** current (fully resolved) config */
-  grpc_client_config *resolved_config;
-
-  /** zookeeper handle */
-  zhandle_t *zookeeper_handle;
-  /** zookeeper resolved addresses */
-  grpc_resolved_addresses *resolved_addrs;
-  /** total number of addresses to be resolved */
-  int resolved_total;
-  /** number of addresses resolved */
-  int resolved_num;
-} zookeeper_resolver;
-
-static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-
-static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
-static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                               zookeeper_resolver *r);
-
-static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *r);
-static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                           grpc_client_config **target_config,
-                           grpc_closure *on_complete);
-
-static const grpc_resolver_vtable zookeeper_resolver_vtable = {
-    zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
-    zookeeper_next};
-
-static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
-                               grpc_resolver *resolver) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  grpc_closure *call = NULL;
-  gpr_mu_lock(&r->mu);
-  if (r->next_completion != NULL) {
-    *r->target_config = NULL;
-    call = r->next_completion;
-    r->next_completion = NULL;
-  }
-  zookeeper_close(r->zookeeper_handle);
-  gpr_mu_unlock(&r->mu);
-  if (call != NULL) {
-    call->cb(exec_ctx, call->cb_arg, 1);
-  }
-}
-
-static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *resolver) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  if (r->resolving == 0) {
-    zookeeper_start_resolving_locked(r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                           grpc_client_config **target_config,
-                           grpc_closure *on_complete) {
-  zookeeper_resolver *r = (zookeeper_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(r->next_completion == NULL);
-  r->next_completion = on_complete;
-  r->target_config = target_config;
-  if (r->resolved_version == 0 && r->resolving == 0) {
-    zookeeper_start_resolving_locked(r);
-  } else {
-    zookeeper_maybe_finish_next_locked(exec_ctx, r);
-  }
-  gpr_mu_unlock(&r->mu);
-}
-
-/** Zookeeper global watcher for connection management
-    TODO: better connection management besides logs */
-static void zookeeper_global_watcher(zhandle_t *zookeeper_handle, int type,
-                                     int state, const char *path,
-                                     void *watcher_ctx) {
-  if (type == ZOO_SESSION_EVENT) {
-    if (state == ZOO_EXPIRED_SESSION_STATE) {
-      gpr_log(GPR_ERROR, "Zookeeper session expired");
-    } else if (state == ZOO_AUTH_FAILED_STATE) {
-      gpr_log(GPR_ERROR, "Zookeeper authentication failed");
-    }
-  }
-}
-
-/** Zookeeper watcher triggered by changes to watched nodes
-    Once triggered, it tries to resolve again to get updated addresses */
-static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
-                              const char *path, void *watcher_ctx) {
-  if (watcher_ctx != NULL) {
-    zookeeper_resolver *r = (zookeeper_resolver *)watcher_ctx;
-    if (state == ZOO_CONNECTED_STATE) {
-      gpr_mu_lock(&r->mu);
-      if (r->resolving == 0) {
-        zookeeper_start_resolving_locked(r);
-      }
-      gpr_mu_unlock(&r->mu);
-    }
-  }
-}
-
-/** Callback function after getting all resolved addresses
-    Creates a subchannel for each address */
-static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                                  grpc_resolved_addresses *addresses) {
-  zookeeper_resolver *r = arg;
-  grpc_client_config *config = NULL;
-  grpc_lb_policy *lb_policy;
-
-  if (addresses != NULL) {
-    grpc_lb_policy_args lb_policy_args;
-    config = grpc_client_config_create();
-    lb_policy_args.addresses = addresses;
-    lb_policy_args.client_channel_factory = r->client_channel_factory;
-    lb_policy =
-        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
-
-    if (lb_policy != NULL) {
-      grpc_client_config_set_lb_policy(config, lb_policy);
-      GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
-    }
-    grpc_resolved_addresses_destroy(addresses);
-  }
-  gpr_mu_lock(&r->mu);
-  GPR_ASSERT(r->resolving == 1);
-  r->resolving = 0;
-  if (r->resolved_config != NULL) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  r->resolved_config = config;
-  r->resolved_version++;
-  zookeeper_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
-
-  GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "zookeeper-resolving");
-}
-
-/** Callback function for each DNS resolved address */
-static void zookeeper_dns_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                                   grpc_resolved_addresses *addresses) {
-  size_t i;
-  zookeeper_resolver *r = arg;
-  int resolve_done = 0;
-
-  gpr_mu_lock(&r->mu);
-  r->resolved_num++;
-  r->resolved_addrs->addrs =
-      gpr_realloc(r->resolved_addrs->addrs,
-                  sizeof(grpc_resolved_address) *
-                      (r->resolved_addrs->naddrs + addresses->naddrs));
-  for (i = 0; i < addresses->naddrs; i++) {
-    memcpy(r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].addr,
-           addresses->addrs[i].addr, addresses->addrs[i].len);
-    r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].len =
-        addresses->addrs[i].len;
-  }
-
-  r->resolved_addrs->naddrs += addresses->naddrs;
-  grpc_resolved_addresses_destroy(addresses);
-
-  /** Wait for all addresses to be resolved */
-  resolve_done = (r->resolved_num == r->resolved_total);
-  gpr_mu_unlock(&r->mu);
-  if (resolve_done) {
-    zookeeper_on_resolved(exec_ctx, r, r->resolved_addrs);
-  }
-}
-
-/** Parses JSON format address of a zookeeper node */
-static char *zookeeper_parse_address(const char *value, size_t value_len) {
-  grpc_json *json;
-  grpc_json *cur;
-  const char *host;
-  const char *port;
-  char *buffer;
-  char *address = NULL;
-
-  buffer = gpr_malloc(value_len);
-  memcpy(buffer, value, value_len);
-  json = grpc_json_parse_string_with_len(buffer, value_len);
-  if (json != NULL) {
-    host = NULL;
-    port = NULL;
-    for (cur = json->child; cur != NULL; cur = cur->next) {
-      if (!strcmp(cur->key, "host")) {
-        host = cur->value;
-        if (port != NULL) {
-          break;
-        }
-      } else if (!strcmp(cur->key, "port")) {
-        port = cur->value;
-        if (host != NULL) {
-          break;
-        }
-      }
-    }
-    if (host != NULL && port != NULL) {
-      gpr_asprintf(&address, "%s:%s", host, port);
-    }
-    grpc_json_destroy(json);
-  }
-  gpr_free(buffer);
-
-  return address;
-}
-
-static void zookeeper_get_children_node_completion(int rc, const char *value,
-                                                   int value_len,
-                                                   const struct Stat *stat,
-                                                   const void *arg) {
-  char *address = NULL;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-  int resolve_done = 0;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return;
-  }
-
-  address = zookeeper_parse_address(value, (size_t)value_len);
-  if (address != NULL) {
-    /** Further resolves address by DNS */
-    grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
-    gpr_free(address);
-  } else {
-    gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
-    gpr_mu_lock(&r->mu);
-    r->resolved_total--;
-    resolve_done = (r->resolved_num == r->resolved_total);
-    gpr_mu_unlock(&r->mu);
-    if (resolve_done) {
-      zookeeper_on_resolved(&exec_ctx, r, r->resolved_addrs);
-    }
-  }
-
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void zookeeper_get_children_completion(
-    int rc, const struct String_vector *children, const void *arg) {
-  char *path;
-  int status;
-  int i;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
-    return;
-  }
-
-  if (children->count == 0) {
-    gpr_log(GPR_ERROR, "Error in resolving zookeeper address %s", r->name);
-    return;
-  }
-
-  r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  r->resolved_addrs->addrs = NULL;
-  r->resolved_addrs->naddrs = 0;
-  r->resolved_total = children->count;
-
-  /** TODO: Replace expensive heap allocation with stack
-      if we can get maximum length of zookeeper path */
-  for (i = 0; i < children->count; i++) {
-    gpr_asprintf(&path, "%s/%s", r->name, children->data[i]);
-    status = zoo_awget(r->zookeeper_handle, path, zookeeper_watcher, r,
-                       zookeeper_get_children_node_completion, r);
-    gpr_free(path);
-    if (status != 0) {
-      gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", path);
-    }
-  }
-}
-
-static void zookeeper_get_node_completion(int rc, const char *value,
-                                          int value_len,
-                                          const struct Stat *stat,
-                                          const void *arg) {
-  int status;
-  char *address = NULL;
-  zookeeper_resolver *r = (zookeeper_resolver *)arg;
-  r->resolved_addrs = NULL;
-  r->resolved_total = 0;
-  r->resolved_num = 0;
-
-  if (rc != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
-    return;
-  }
-
-  /** If zookeeper node of path r->name does not have address
-      (i.e. service node), get its children */
-  address = zookeeper_parse_address(value, (size_t)value_len);
-  if (address != NULL) {
-    r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-    r->resolved_addrs->addrs = NULL;
-    r->resolved_addrs->naddrs = 0;
-    r->resolved_total = 1;
-    /** Further resolves address by DNS */
-    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
-    gpr_free(address);
-    grpc_exec_ctx_finish(&exec_ctx);
-    return;
-  }
-
-  status = zoo_awget_children(r->zookeeper_handle, r->name, zookeeper_watcher,
-                              r, zookeeper_get_children_completion, r);
-  if (status != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
-  }
-}
-
-static void zookeeper_resolve_address(zookeeper_resolver *r) {
-  int status;
-  status = zoo_awget(r->zookeeper_handle, r->name, zookeeper_watcher, r,
-                     zookeeper_get_node_completion, r);
-  if (status != 0) {
-    gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
-  }
-}
-
-static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
-  GRPC_RESOLVER_REF(&r->base, "zookeeper-resolving");
-  GPR_ASSERT(r->resolving == 0);
-  r->resolving = 1;
-  zookeeper_resolve_address(r);
-}
-
-static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
-                                               zookeeper_resolver *r) {
-  if (r->next_completion != NULL &&
-      r->resolved_version != r->published_version) {
-    *r->target_config = r->resolved_config;
-    if (r->resolved_config != NULL) {
-      grpc_client_config_ref(r->resolved_config);
-    }
-    grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
-    r->next_completion = NULL;
-    r->published_version = r->resolved_version;
-  }
-}
-
-static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
-  zookeeper_resolver *r = (zookeeper_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
-  if (r->resolved_config != NULL) {
-    grpc_client_config_unref(exec_ctx, r->resolved_config);
-  }
-  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
-  gpr_free(r->name);
-  gpr_free(r->lb_policy_name);
-  gpr_free(r);
-}
-
-static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
-                                       const char *lb_policy_name) {
-  zookeeper_resolver *r;
-  size_t length;
-  char *path = args->uri->path;
-
-  if (0 == strcmp(args->uri->authority, "")) {
-    gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
-    return NULL;
-  }
-
-  /** Removes the trailing slash if exists */
-  length = strlen(path);
-  if (length > 1 && path[length - 1] == '/') {
-    path[length - 1] = 0;
-  }
-
-  r = gpr_malloc(sizeof(zookeeper_resolver));
-  memset(r, 0, sizeof(*r));
-  gpr_ref_init(&r->refs, 1);
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
-  r->name = gpr_strdup(path);
-
-  r->client_channel_factory = args->client_channel_factory;
-  grpc_client_channel_factory_ref(r->client_channel_factory);
-
-  r->lb_policy_name = gpr_strdup(lb_policy_name);
-
-  /** Initializes zookeeper client */
-  zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
-  r->zookeeper_handle =
-      zookeeper_init(args->uri->authority, zookeeper_global_watcher,
-                     GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
-  if (r->zookeeper_handle == NULL) {
-    gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
-    return NULL;
-  }
-
-  return &r->base;
-}
-
-/*
- * FACTORY
- */
-
-static void zookeeper_factory_ref(grpc_resolver_factory *factory) {}
-
-static void zookeeper_factory_unref(grpc_resolver_factory *factory) {}
-
-static char *zookeeper_factory_get_default_hostname(
-    grpc_resolver_factory *factory, grpc_uri *uri) {
-  return NULL;
-}
-
-static grpc_resolver *zookeeper_factory_create_resolver(
-    grpc_resolver_factory *factory, grpc_resolver_args *args) {
-  return zookeeper_create(args, "pick_first");
-}
-
-static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
-    zookeeper_factory_ref, zookeeper_factory_unref,
-    zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
-    "zookeeper"};
-
-static grpc_resolver_factory zookeeper_resolver_factory = {
-    &zookeeper_factory_vtable};
-
-static grpc_resolver_factory *zookeeper_resolver_factory_create() {
-  return &zookeeper_resolver_factory;
-}
-
-static void zookeeper_plugin_init() {
-  grpc_register_resolver_type(zookeeper_resolver_factory_create());
-}
-
-void grpc_zookeeper_register() {
-  GRPC_API_TRACE("grpc_zookeeper_register(void)", 0, ());
-  grpc_register_plugin(zookeeper_plugin_init, NULL);
-}
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index c5d3d8d..85f9efb 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -79,11 +79,11 @@
 }
 
 static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
+                                           grpc_error *error) {
   connector_unref(exec_ctx, arg);
 }
 
-static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   connector *c = arg;
   grpc_closure *notify;
   grpc_endpoint *tcp = c->tcp;
@@ -103,13 +103,13 @@
     grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
                                         0);
     GPR_ASSERT(c->result->transport);
-    c->result->channel_args = c->args.channel_args;
+    c->result->channel_args = grpc_channel_args_copy(c->args.channel_args);
   } else {
     memset(c->result, 0, sizeof(*c->result));
   }
   notify = c->notify;
   c->notify = NULL;
-  notify->cb(exec_ctx, notify->cb_arg, 1);
+  grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
 }
 
 static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index a262306..721ba82 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -90,7 +90,6 @@
                                      grpc_auth_context *auth_context) {
   connector *c = arg;
   grpc_closure *notify;
-  grpc_channel_args *args_copy = NULL;
   gpr_mu_lock(&c->mu);
   if (c->connecting_endpoint == NULL) {
     memset(c->result, 0, sizeof(*c->result));
@@ -109,26 +108,23 @@
     grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
                                         0);
     auth_context_arg = grpc_auth_context_to_arg(auth_context);
-    args_copy = grpc_channel_args_copy_and_add(c->args.channel_args,
-                                               &auth_context_arg, 1);
-    c->result->channel_args = args_copy;
+    c->result->channel_args = grpc_channel_args_copy_and_add(
+        c->args.channel_args, &auth_context_arg, 1);
   }
   notify = c->notify;
   c->notify = NULL;
-  /* look at c->args which are connector args. */
-  notify->cb(exec_ctx, notify->cb_arg, 1);
-  if (args_copy != NULL) grpc_channel_args_destroy(args_copy);
+  grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_NONE, NULL);
 }
 
 static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
-                                           bool success) {
+                                           grpc_error *error) {
   connector *c = arg;
-  grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
-                                               c->connecting_endpoint,
-                                               on_secure_handshake_done, c);
+  grpc_channel_security_connector_do_handshake(
+      exec_ctx, c->security_connector, c->connecting_endpoint, c->args.deadline,
+      on_secure_handshake_done, c);
 }
 
-static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   connector *c = arg;
   grpc_closure *notify;
   grpc_endpoint *tcp = c->newly_connecting_endpoint;
@@ -147,13 +143,14 @@
                           &c->initial_string_sent);
     } else {
       grpc_channel_security_connector_do_handshake(
-          exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
+          exec_ctx, c->security_connector, tcp, c->args.deadline,
+          on_secure_handshake_done, c);
     }
   } else {
     memset(c->result, 0, sizeof(*c->result));
     notify = c->notify;
     c->notify = NULL;
-    notify->cb(exec_ctx, notify->cb_arg, 1);
+    grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
   }
 }
 
@@ -175,7 +172,6 @@
                               grpc_closure *notify) {
   connector *c = (connector *)con;
   GPR_ASSERT(c->notify == NULL);
-  GPR_ASSERT(notify->cb);
   c->notify = notify;
   c->args = *args;
   c->result = result;
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
index c95dd20..9bae3a9 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -35,6 +35,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/channel/http_server_filter.h"
@@ -74,34 +75,40 @@
                     grpc_closure *destroy_done) {
   grpc_tcp_server *tcp = tcpp;
   grpc_tcp_server_unref(exec_ctx, tcp);
-  grpc_exec_ctx_enqueue(exec_ctx, destroy_done, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL);
 }
 
 int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
   grpc_resolved_addresses *resolved = NULL;
   grpc_tcp_server *tcp = NULL;
   size_t i;
-  unsigned count = 0;
+  size_t count = 0;
   int port_num = -1;
   int port_temp;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_error *err = GRPC_ERROR_NONE;
 
   GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2,
                  (server, addr));
 
-  resolved = grpc_blocking_resolve_address(addr, "http");
-  if (!resolved) {
+  grpc_error **errors = NULL;
+  err = grpc_blocking_resolve_address(addr, "https", &resolved);
+  if (err != GRPC_ERROR_NONE) {
     goto error;
   }
 
-  tcp = grpc_tcp_server_create(NULL);
-  GPR_ASSERT(tcp);
+  err = grpc_tcp_server_create(NULL, &tcp);
+  if (err != GRPC_ERROR_NONE) {
+    goto error;
+  }
 
-  for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
+  const size_t naddrs = resolved->naddrs;
+  errors = gpr_malloc(sizeof(*errors) * naddrs);
+  for (i = 0; i < naddrs; i++) {
+    errors[i] = grpc_tcp_server_add_port(
         tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len);
-    if (port_temp > 0) {
+        resolved->addrs[i].len, &port_temp);
+    if (errors[i] == GRPC_ERROR_NONE) {
       if (port_num == -1) {
         port_num = port_temp;
       } else {
@@ -111,14 +118,24 @@
     }
   }
   if (count == 0) {
-    gpr_log(GPR_ERROR, "No address added out of total %" PRIuPTR " resolved",
-            resolved->naddrs);
+    char *msg;
+    gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
+                 naddrs);
+    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
+    gpr_free(msg);
     goto error;
-  }
-  if (count != resolved->naddrs) {
-    gpr_log(GPR_ERROR,
-            "Only %d addresses added out of total %" PRIuPTR " resolved", count,
-            resolved->naddrs);
+  } else if (count != naddrs) {
+    char *msg;
+    gpr_asprintf(&msg, "Only %" PRIuPTR
+                       " addresses added out of total %" PRIuPTR " resolved",
+                 count, naddrs);
+    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
+    gpr_free(msg);
+
+    const char *warning_message = grpc_error_string(err);
+    gpr_log(GPR_INFO, "WARNING: %s", warning_message);
+    grpc_error_free_string(warning_message);
+    /* we managed to bind some addresses: continue */
   }
   grpc_resolved_addresses_destroy(resolved);
 
@@ -128,6 +145,7 @@
 
 /* Error path: cleanup and return */
 error:
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
   if (resolved) {
     grpc_resolved_addresses_destroy(resolved);
   }
@@ -136,7 +154,18 @@
   }
   port_num = 0;
 
+  const char *msg = grpc_error_string(err);
+  gpr_log(GPR_ERROR, "%s", msg);
+  grpc_error_free_string(msg);
+  GRPC_ERROR_UNREF(err);
+
 done:
   grpc_exec_ctx_finish(&exec_ctx);
+  if (errors != NULL) {
+    for (i = 0; i < naddrs; i++) {
+      GRPC_ERROR_UNREF(errors[i]);
+    }
+  }
+  gpr_free(errors);
   return port_num;
 }
diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
index e3437e5..ead8a4d 100644
--- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -37,6 +37,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/useful.h>
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
@@ -128,9 +129,11 @@
   state->state = statep;
   state_ref(state->state);
   state->accepting_pollset = accepting_pollset;
-  grpc_server_security_connector_do_handshake(exec_ctx, state->state->sc,
-                                              acceptor, tcp,
-                                              on_secure_handshake_done, state);
+  grpc_server_security_connector_do_handshake(
+      exec_ctx, state->state->sc, acceptor, tcp,
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                   gpr_time_from_seconds(120, GPR_TIMESPAN)),
+      on_secure_handshake_done, state);
 }
 
 /* Server callback: start listening on our ports */
@@ -141,11 +144,12 @@
                         on_accept, state);
 }
 
-static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) {
+static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep,
+                         grpc_error *error) {
   server_secure_state *state = statep;
   if (state->destroy_callback != NULL) {
     state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
-                                success);
+                                GRPC_ERROR_REF(error));
   }
   grpc_server_security_connector_shutdown(exec_ctx, state->sc);
   state_unref(state);
@@ -171,12 +175,14 @@
   grpc_tcp_server *tcp = NULL;
   server_secure_state *state = NULL;
   size_t i;
-  unsigned count = 0;
+  size_t count = 0;
   int port_num = -1;
   int port_temp;
   grpc_security_status status = GRPC_SECURITY_ERROR;
   grpc_server_security_connector *sc = NULL;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_error *err = GRPC_ERROR_NONE;
+  grpc_error **errors = NULL;
 
   GRPC_API_TRACE(
       "grpc_server_add_secure_http2_port("
@@ -184,26 +190,34 @@
       3, (server, addr, creds));
 
   /* create security context */
-  if (creds == NULL) goto error;
+  if (creds == NULL) {
+    err = GRPC_ERROR_CREATE(
+        "No credentials specified for secure server port (creds==NULL)");
+    goto error;
+  }
   status = grpc_server_credentials_create_security_connector(creds, &sc);
   if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR,
-            "Unable to create secure server with credentials of type %s.",
-            creds->type);
+    char *msg;
+    gpr_asprintf(&msg,
+                 "Unable to create secure server with credentials of type %s.",
+                 creds->type);
+    err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
+                             GRPC_ERROR_INT_SECURITY_STATUS, status);
+    gpr_free(msg);
     goto error;
   }
   sc->channel_args = grpc_server_get_channel_args(server);
 
   /* resolve address */
-  resolved = grpc_blocking_resolve_address(addr, "https");
-  if (!resolved) {
+  err = grpc_blocking_resolve_address(addr, "https", &resolved);
+  if (err != GRPC_ERROR_NONE) {
     goto error;
   }
   state = gpr_malloc(sizeof(*state));
   memset(state, 0, sizeof(*state));
   grpc_closure_init(&state->destroy_closure, destroy_done, state);
-  tcp = grpc_tcp_server_create(&state->destroy_closure);
-  if (!tcp) {
+  err = grpc_tcp_server_create(&state->destroy_closure, &tcp);
+  if (err != GRPC_ERROR_NONE) {
     goto error;
   }
 
@@ -215,11 +229,12 @@
   gpr_mu_init(&state->mu);
   gpr_ref_init(&state->refcount, 1);
 
+  errors = gpr_malloc(sizeof(*errors) * resolved->naddrs);
   for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
+    errors[i] = grpc_tcp_server_add_port(
         tcp, (struct sockaddr *)&resolved->addrs[i].addr,
-        resolved->addrs[i].len);
-    if (port_temp > 0) {
+        resolved->addrs[i].len, &port_temp);
+    if (errors[i] == GRPC_ERROR_NONE) {
       if (port_num == -1) {
         port_num = port_temp;
       } else {
@@ -229,16 +244,31 @@
     }
   }
   if (count == 0) {
-    gpr_log(GPR_ERROR, "No address added out of total %" PRIuPTR " resolved",
-            resolved->naddrs);
+    char *msg;
+    gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
+                 resolved->naddrs);
+    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
+    gpr_free(msg);
     goto error;
+  } else if (count != resolved->naddrs) {
+    char *msg;
+    gpr_asprintf(&msg, "Only %" PRIuPTR
+                       " addresses added out of total %" PRIuPTR " resolved",
+                 count, resolved->naddrs);
+    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
+    gpr_free(msg);
+
+    const char *warning_message = grpc_error_string(err);
+    gpr_log(GPR_INFO, "WARNING: %s", warning_message);
+    grpc_error_free_string(warning_message);
+    /* we managed to bind some addresses: continue */
+  } else {
+    for (i = 0; i < resolved->naddrs; i++) {
+      GRPC_ERROR_UNREF(errors[i]);
+    }
   }
-  if (count != resolved->naddrs) {
-    gpr_log(GPR_ERROR,
-            "Only %d addresses added out of total %" PRIuPTR " resolved", count,
-            resolved->naddrs);
-    /* if it's an error, don't we want to goto error; here ? */
-  }
+  gpr_free(errors);
+  errors = NULL;
   grpc_resolved_addresses_destroy(resolved);
 
   /* Register with the server only upon success */
@@ -249,6 +279,13 @@
 
 /* Error path: cleanup and return */
 error:
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
+  if (errors != NULL) {
+    for (i = 0; i < resolved->naddrs; i++) {
+      GRPC_ERROR_UNREF(errors[i]);
+    }
+    gpr_free(errors);
+  }
   if (resolved) {
     grpc_resolved_addresses_destroy(resolved);
   }
@@ -263,5 +300,9 @@
     }
   }
   grpc_exec_ctx_finish(&exec_ctx);
+  const char *msg = grpc_error_string(err);
+  GRPC_ERROR_UNREF(err);
+  gpr_log(GPR_ERROR, "%s", msg);
+  grpc_error_free_string(msg);
   return 0;
 }
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 6e8640f..9aa39ba 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -85,19 +85,17 @@
 static const grpc_transport_vtable vtable;
 
 /* forward declarations of various callbacks that we'll build closures around */
-static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
-                           bool iomgr_success_ignored);
-static void reading_action(grpc_exec_ctx *exec_ctx, void *t,
-                           bool iomgr_success_ignored);
-static void parsing_action(grpc_exec_ctx *exec_ctx, void *t,
-                           bool iomgr_success_ignored);
+static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
+static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
+static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
 
 /** Set a transport level setting, and push it to our peer */
 static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
                          uint32_t value);
 
 /** Start disconnection chain */
-static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
+static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                            grpc_error *error);
 
 /** Perform a transport_op */
 static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
@@ -135,7 +133,7 @@
 
 static void connectivity_state_set(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_connectivity_state state, const char *reason);
+    grpc_connectivity_state state, grpc_error *error, const char *reason);
 
 static void check_read_ops(grpc_exec_ctx *exec_ctx,
                            grpc_chttp2_transport_global *transport_global);
@@ -149,7 +147,9 @@
                                                 grpc_chttp2_stream *s,
                                                 void *byte_stream);
 static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
-                                grpc_chttp2_stream_global *stream_global);
+                                grpc_chttp2_transport_global *transport_global,
+                                grpc_chttp2_stream_global *stream_global,
+                                grpc_error *error);
 
 /*******************************************************************************
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
@@ -194,7 +194,8 @@
      and maybe they hold resources that need to be freed */
   while (t->global.pings.next != &t->global.pings) {
     grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
-    grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, ping->on_recv,
+                        GRPC_ERROR_CREATE("Transport closed"), NULL);
     ping->next->prev = ping->prev;
     ping->prev->next = ping->next;
     gpr_free(ping);
@@ -409,7 +410,7 @@
                                      grpc_chttp2_stream *s_ignored,
                                      void *arg_ignored) {
   t->destroying = 1;
-  drop_connection(exec_ctx, t);
+  drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
 }
 
 static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
@@ -445,12 +446,11 @@
 
 static void close_transport_locked(grpc_exec_ctx *exec_ctx,
                                    grpc_chttp2_transport *t,
-                                   grpc_chttp2_stream *s_ignored,
-                                   void *arg_ignored) {
+                                   grpc_error *error) {
   if (!t->closed) {
     t->closed = 1;
     connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN,
-                           "close_transport");
+                           GRPC_ERROR_REF(error), "close_transport");
     if (t->ep) {
       allow_endpoint_shutdown_locked(exec_ctx, t);
     }
@@ -463,6 +463,7 @@
       GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
     }
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 #ifdef GRPC_STREAM_REFCOUNT_DEBUG
@@ -551,7 +552,9 @@
              s->global.id == 0);
   GPR_ASSERT(!s->global.in_stream_map);
   if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
-    close_transport_locked(exec_ctx, t, NULL, NULL);
+    close_transport_locked(
+        exec_ctx, t,
+        GRPC_ERROR_CREATE("Last stream closed after sending goaway"));
   }
   if (!t->executor.parsing_active && s->global.id) {
     GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
@@ -645,7 +648,7 @@
       t->executor.writing_active = 1;
       REF_TRANSPORT(t, "writing");
       prevent_endpoint_shutdown(t);
-      grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
     }
     check_read_ops(exec_ctx, &t->global);
 
@@ -756,12 +759,12 @@
                                         grpc_chttp2_transport *t,
                                         grpc_chttp2_stream *s_ignored,
                                         void *a) {
-  bool success = (bool)(uintptr_t)a;
+  grpc_error *error = a;
 
   allow_endpoint_shutdown_locked(exec_ctx, t);
 
-  if (!success) {
-    drop_connection(exec_ctx, t);
+  if (error != GRPC_ERROR_NONE) {
+    drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
   }
 
   grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
@@ -769,7 +772,8 @@
   grpc_chttp2_stream_global *stream_global;
   while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
                                                          &stream_global)) {
-    fail_pending_writes(exec_ctx, stream_global);
+    fail_pending_writes(exec_ctx, &t->global, stream_global,
+                        GRPC_ERROR_REF(error));
     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
   }
 
@@ -782,18 +786,18 @@
   }
 
   UNREF_TRANSPORT(exec_ctx, t, "writing");
+  GRPC_ERROR_UNREF(error);
 }
 
 void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
-                                   void *transport_writing, bool success) {
+                                   void *transport_writing, grpc_error *error) {
   grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
-  grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL,
-                                   terminate_writing_with_lock,
-                                   (void *)(uintptr_t)success, 0);
+  grpc_chttp2_run_with_global_lock(
+      exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0);
 }
 
 static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
-                           bool iomgr_success_ignored) {
+                           grpc_error *error) {
   grpc_chttp2_transport *t = gt;
   GPR_TIMER_BEGIN("writing_action", 0);
   grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
@@ -806,13 +810,19 @@
   char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
   GRPC_CHTTP2_IF_TRACING(
       gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
-  gpr_free(msg);
   gpr_slice_unref(goaway_text);
   transport_global->seen_goaway = 1;
   /* lie: use transient failure from the transport to indicate goaway has been
    * received */
-  connectivity_state_set(exec_ctx, transport_global,
-                         GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway");
+  connectivity_state_set(
+      exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
+      grpc_error_set_str(
+          grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
+                             GRPC_ERROR_INT_HTTP2_ERROR,
+                             (intptr_t)goaway_error),
+          GRPC_ERROR_STR_RAW_BYTES, msg),
+      "got_goaway");
+  gpr_free(msg);
 }
 
 static void maybe_start_some_streams(
@@ -841,9 +851,9 @@
     transport_global->next_stream_id += 2;
 
     if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
-      connectivity_state_set(exec_ctx, transport_global,
-                             GRPC_CHANNEL_TRANSIENT_FAILURE,
-                             "no_more_stream_ids");
+      connectivity_state_set(
+          exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
+          GRPC_ERROR_CREATE("Stream IDs exhausted"), "no_more_stream_ids");
     }
 
     stream_global->outgoing_window =
@@ -871,34 +881,40 @@
 }
 
 #define CLOSURE_BARRIER_STATS_BIT (1 << 0)
-#define CLOSURE_BARRIER_FAILURE_BIT (1 << 1)
 #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
 
 static grpc_closure *add_closure_barrier(grpc_closure *closure) {
-  closure->final_data += CLOSURE_BARRIER_FIRST_REF_BIT;
+  closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
   return closure;
 }
 
-void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
-                                       grpc_chttp2_stream_global *stream_global,
-                                       grpc_closure **pclosure, int success) {
+void grpc_chttp2_complete_closure_step(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
+    grpc_error *error) {
   grpc_closure *closure = *pclosure;
   if (closure == NULL) {
+    GRPC_ERROR_UNREF(error);
     return;
   }
-  closure->final_data -= CLOSURE_BARRIER_FIRST_REF_BIT;
-  if (!success) {
-    closure->final_data |= CLOSURE_BARRIER_FAILURE_BIT;
+  closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
+  if (error != GRPC_ERROR_NONE) {
+    if (closure->error == GRPC_ERROR_NONE) {
+      closure->error =
+          GRPC_ERROR_CREATE("Error in HTTP transport completing operation");
+      closure->error = grpc_error_set_str(
+          closure->error, GRPC_ERROR_STR_TARGET_ADDRESS,
+          TRANSPORT_FROM_GLOBAL(transport_global)->peer_string);
+    }
+    closure->error = grpc_error_add_child(closure->error, error);
   }
-  if (closure->final_data < CLOSURE_BARRIER_FIRST_REF_BIT) {
-    if (closure->final_data & CLOSURE_BARRIER_STATS_BIT) {
+  if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
+    if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
       grpc_transport_move_stats(&stream_global->stats,
                                 stream_global->collecting_stats);
       stream_global->collecting_stats = NULL;
     }
-    grpc_exec_ctx_enqueue(
-        exec_ctx, closure,
-        (closure->final_data & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, closure->error, NULL);
   }
   *pclosure = NULL;
 }
@@ -916,7 +932,7 @@
   return 0;
 }
 
-static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
 
 static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
                                      grpc_chttp2_transport *t,
@@ -933,12 +949,13 @@
   }
   /* use final_data as a barrier until enqueue time; the inital counter is
      dropped at the end of this function */
-  on_complete->final_data = CLOSURE_BARRIER_FIRST_REF_BIT;
+  on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
+  on_complete->error = GRPC_ERROR_NONE;
 
   if (op->collect_stats != NULL) {
     GPR_ASSERT(stream_global->collecting_stats == NULL);
     stream_global->collecting_stats = op->collect_stats;
-    on_complete->final_data |= CLOSURE_BARRIER_STATS_BIT;
+    on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
   }
 
   if (op->cancel_with_status != GRPC_STATUS_OK) {
@@ -985,8 +1002,10 @@
         }
       } else {
         grpc_chttp2_complete_closure_step(
-            exec_ctx, stream_global,
-            &stream_global->send_initial_metadata_finished, 0);
+            exec_ctx, transport_global, stream_global,
+            &stream_global->send_initial_metadata_finished,
+            GRPC_ERROR_CREATE(
+                "Attempt to send initial metadata after stream was closed"));
       }
     }
   }
@@ -997,7 +1016,9 @@
     stream_global->send_message_finished = add_closure_barrier(on_complete);
     if (stream_global->write_closed) {
       grpc_chttp2_complete_closure_step(
-          exec_ctx, stream_global, &stream_global->send_message_finished, 0);
+          exec_ctx, transport_global, stream_global,
+          &stream_global->send_message_finished,
+          GRPC_ERROR_CREATE("Attempt to send message after stream was closed"));
     } else {
       stream_global->send_message = op->send_message;
       if (stream_global->id != 0) {
@@ -1031,9 +1052,12 @@
       }
       if (stream_global->write_closed) {
         grpc_chttp2_complete_closure_step(
-            exec_ctx, stream_global,
+            exec_ctx, transport_global, stream_global,
             &stream_global->send_trailing_metadata_finished,
-            grpc_metadata_batch_is_empty(op->send_trailing_metadata));
+            grpc_metadata_batch_is_empty(op->send_trailing_metadata)
+                ? GRPC_ERROR_NONE
+                : GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
+                                    "stream was closed"));
       } else if (stream_global->id != 0) {
         /* TODO(ctiller): check if there's flow control for any outstanding
            bytes before going writable */
@@ -1072,7 +1096,8 @@
     grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
   }
 
-  grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1);
+  grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
+                                    &on_complete, GRPC_ERROR_NONE);
 
   GPR_TIMER_END("perform_stream_op_locked", 0);
 }
@@ -1109,7 +1134,7 @@
   for (ping = transport_global->pings.next; ping != &transport_global->pings;
        ping = ping->next) {
     if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
-      grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL);
       ping->next->prev = ping->prev;
       ping->prev->next = ping->next;
       gpr_free(ping);
@@ -1131,7 +1156,7 @@
                                         grpc_chttp2_stream *s_unused,
                                         void *stream_op) {
   grpc_transport_op *op = stream_op;
-  bool close_transport = op->disconnect;
+  grpc_error *close_transport = op->disconnect_with_error;
 
   /* If there's a set_accept_stream ensure that we're not parsing
      to avoid changing things out from underneath */
@@ -1142,7 +1167,7 @@
     return;
   }
 
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
 
   if (op->on_connectivity_state_change != NULL) {
     grpc_connectivity_state_notify_on_state_change(
@@ -1156,7 +1181,9 @@
         t->global.last_incoming_stream_id,
         (uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
         gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
-    close_transport = !grpc_chttp2_has_streams(t);
+    close_transport = grpc_chttp2_has_streams(t)
+                          ? GRPC_ERROR_NONE
+                          : GRPC_ERROR_CREATE("GOAWAY sent");
   }
 
   if (op->set_accept_stream) {
@@ -1177,8 +1204,8 @@
     send_ping_locked(t, op->send_ping);
   }
 
-  if (close_transport) {
-    close_transport_locked(exec_ctx, t, NULL, NULL);
+  if (close_transport != GRPC_ERROR_NONE) {
+    close_transport_locked(exec_ctx, t, close_transport);
   }
 }
 
@@ -1214,8 +1241,8 @@
       grpc_chttp2_incoming_metadata_buffer_publish(
           &stream_global->received_initial_metadata,
           stream_global->recv_initial_metadata);
-      grpc_exec_ctx_enqueue(
-          exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, stream_global->recv_initial_metadata_ready,
+                          GRPC_ERROR_NONE, NULL);
       stream_global->recv_initial_metadata_ready = NULL;
     }
     if (stream_global->recv_message_ready != NULL) {
@@ -1228,13 +1255,13 @@
         *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
             &stream_global->incoming_frames);
         GPR_ASSERT(*stream_global->recv_message != NULL);
-        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
-                              NULL);
+        grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
+                            GRPC_ERROR_NONE, NULL);
         stream_global->recv_message_ready = NULL;
       } else if (stream_global->published_trailing_metadata) {
         *stream_global->recv_message = NULL;
-        grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
-                              NULL);
+        grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
+                            GRPC_ERROR_NONE, NULL);
         stream_global->recv_message_ready = NULL;
       }
     }
@@ -1255,8 +1282,8 @@
             &stream_global->received_trailing_metadata,
             stream_global->recv_trailing_metadata);
         grpc_chttp2_complete_closure_step(
-            exec_ctx, stream_global,
-            &stream_global->recv_trailing_metadata_finished, 1);
+            exec_ctx, transport_global, stream_global,
+            &stream_global->recv_trailing_metadata_finished, GRPC_ERROR_NONE);
       }
     }
   }
@@ -1272,7 +1299,7 @@
 }
 
 static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                          uint32_t id) {
+                          uint32_t id, grpc_error *error) {
   size_t new_stream_count;
   grpc_chttp2_stream *s =
       grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
@@ -1287,12 +1314,15 @@
   }
   if (s->parsing.data_parser.parsing_frame != NULL) {
     grpc_chttp2_incoming_byte_stream_finished(
-        exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
+        exec_ctx, s->parsing.data_parser.parsing_frame,
+        GRPC_ERROR_CREATE_REFERENCING("Stream removed", &error, 1), 0);
     s->parsing.data_parser.parsing_frame = NULL;
   }
 
   if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
-    close_transport_locked(exec_ctx, t, NULL, NULL);
+    close_transport_locked(
+        exec_ctx, t,
+        GRPC_ERROR_CREATE("Last stream closed after sending GOAWAY"));
   }
   if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
@@ -1305,6 +1335,7 @@
     t->global.concurrent_stream_count = (uint32_t)new_stream_count;
     maybe_start_some_streams(exec_ctx, &t->global);
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 static void cancel_from_api(grpc_exec_ctx *exec_ctx,
@@ -1332,8 +1363,10 @@
     stream_global->seen_error = true;
     grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
   }
-  grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
-                                 1);
+  grpc_chttp2_mark_stream_closed(
+      exec_ctx, transport_global, stream_global, 1, 1,
+      grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
+                         GRPC_ERROR_INT_GRPC_STATUS, status));
 }
 
 void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
@@ -1374,23 +1407,27 @@
 }
 
 static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
-                                grpc_chttp2_stream_global *stream_global) {
+                                grpc_chttp2_transport_global *transport_global,
+                                grpc_chttp2_stream_global *stream_global,
+                                grpc_error *error) {
   grpc_chttp2_complete_closure_step(
-      exec_ctx, stream_global, &stream_global->send_initial_metadata_finished,
-      0);
+      exec_ctx, transport_global, stream_global,
+      &stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error));
   grpc_chttp2_complete_closure_step(
-      exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished,
-      0);
-  grpc_chttp2_complete_closure_step(exec_ctx, stream_global,
-                                    &stream_global->send_message_finished, 0);
+      exec_ctx, transport_global, stream_global,
+      &stream_global->send_trailing_metadata_finished, GRPC_ERROR_REF(error));
+  grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
+                                    &stream_global->send_message_finished,
+                                    error);
 }
 
 void grpc_chttp2_mark_stream_closed(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, int close_reads,
-    int close_writes) {
+    grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
+    grpc_error *error) {
   if (stream_global->read_closed && stream_global->write_closed) {
     /* already closed */
+    GRPC_ERROR_UNREF(error);
     return;
   }
   grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
@@ -1407,7 +1444,8 @@
       grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
                                                       stream_global);
     } else {
-      fail_pending_writes(exec_ctx, stream_global);
+      fail_pending_writes(exec_ctx, transport_global, stream_global,
+                          GRPC_ERROR_REF(error));
     }
   }
   if (stream_global->read_closed && stream_global->write_closed) {
@@ -1418,11 +1456,12 @@
     } else {
       if (stream_global->id != 0) {
         remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
-                      stream_global->id);
+                      stream_global->id, GRPC_ERROR_REF(error));
       }
       GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
     }
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 static void close_from_api(grpc_exec_ctx *exec_ctx,
@@ -1529,8 +1568,16 @@
 
   grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
                           optional_message);
+  grpc_error *err = GRPC_ERROR_CREATE("Stream closed");
+  err = grpc_error_set_int(err, GRPC_ERROR_INT_GRPC_STATUS, status);
+  if (optional_message) {
+    char *str =
+        gpr_dump_slice(*optional_message, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    err = grpc_error_set_str(err, GRPC_ERROR_STR_GRPC_MESSAGE, str);
+    gpr_free(str);
+  }
   grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
-                                 1);
+                                 1, err);
 }
 
 static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
@@ -1549,8 +1596,9 @@
   grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
 }
 
-static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  close_transport_locked(exec_ctx, t, NULL, NULL);
+static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                            grpc_error *error) {
+  close_transport_locked(exec_ctx, t, error);
   end_all_the_calls(exec_ctx, t);
 }
 
@@ -1581,20 +1629,22 @@
 static void reading_action_locked(grpc_exec_ctx *exec_ctx,
                                   grpc_chttp2_transport *t,
                                   grpc_chttp2_stream *s_unused, void *arg);
-static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success);
+static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
+                           grpc_error *error);
 static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
                                        grpc_chttp2_transport *t,
                                        grpc_chttp2_stream *s_unused, void *arg);
 static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                               grpc_chttp2_stream *s_unused, void *arg);
 
-static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
+static void reading_action(grpc_exec_ctx *exec_ctx, void *tp,
+                           grpc_error *error) {
   /* Control flow:
      reading_action_locked ->
        (parse_unlocked -> post_parse_locked)? ->
        post_reading_action_locked */
   grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked,
-                                   (void *)(uintptr_t)success, 0);
+                                   GRPC_ERROR_REF(error), 0);
 }
 
 static void reading_action_locked(grpc_exec_ctx *exec_ctx,
@@ -1602,7 +1652,7 @@
                                   grpc_chttp2_stream *s_unused, void *arg) {
   grpc_chttp2_transport_global *transport_global = &t->global;
   grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
-  bool success = (bool)(uintptr_t)arg;
+  grpc_error *error = arg;
 
   GPR_ASSERT(!t->executor.parsing_active);
   if (!t->closed) {
@@ -1611,48 +1661,54 @@
     grpc_chttp2_stream_map_move_into(&t->new_stream_map,
                                      &t->parsing_stream_map);
     grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
-    grpc_exec_ctx_enqueue(exec_ctx, &t->parsing_action, success, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL);
   } else {
     post_reading_action_locked(exec_ctx, t, s_unused, arg);
   }
 }
 
-static bool try_http_parsing(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport *t) {
+static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
+                                    grpc_chttp2_transport *t) {
   grpc_http_parser parser;
   size_t i = 0;
-  bool success = false;
+  grpc_error *error = GRPC_ERROR_NONE;
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
 
-  grpc_http_parser_init(&parser);
+  grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
 
-  for (; i < t->read_buffer.count &&
-         grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
-       i++)
-    ;
-  if (grpc_http_parser_eof(&parser) && parser.type == GRPC_HTTP_RESPONSE) {
-    success = true;
-    GRPC_CHTTP2_IF_TRACING(gpr_log(
-        GPR_DEBUG, "Trying to connect an http1.x server, received status:%d",
-        parser.http.response.status));
+  grpc_error *parse_error = GRPC_ERROR_NONE;
+  for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) {
+    parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
   }
+  if (parse_error == GRPC_ERROR_NONE &&
+      (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
+    error = grpc_error_set_int(
+        GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
+        GRPC_ERROR_INT_HTTP_STATUS, response.status);
+  }
+  GRPC_ERROR_UNREF(parse_error);
 
   grpc_http_parser_destroy(&parser);
-  return success;
+  grpc_http_response_destroy(&response);
+  return error;
 }
 
-static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
+                           grpc_error *error) {
   grpc_chttp2_transport *t = arg;
   GPR_TIMER_BEGIN("reading_action.parse", 0);
   size_t i = 0;
-  for (; i < t->read_buffer.count &&
-         grpc_chttp2_perform_read(exec_ctx, &t->parsing,
-                                  t->read_buffer.slices[i]);
-       i++)
-    ;
+  grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
+                           GRPC_ERROR_NONE};
+  for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
+    errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
+                                         t->read_buffer.slices[i]);
+  };
   if (i != t->read_buffer.count) {
-    success = false;
     gpr_slice_unref(t->optional_drop_message);
-    if (try_http_parsing(exec_ctx, t)) {
+    errors[2] = try_http_parsing(exec_ctx, t);
+    if (errors[2] != GRPC_ERROR_NONE) {
       t->optional_drop_message = gpr_slice_from_copied_string(
           "Connection dropped: received http1.x response");
     } else {
@@ -1660,9 +1716,18 @@
           "Connection dropped: received unparseable response");
     }
   }
+  grpc_error *err =
+      errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
+              errors[2] == GRPC_ERROR_NONE
+          ? GRPC_ERROR_NONE
+          : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
+                                          GPR_ARRAY_SIZE(errors));
+  for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
+    GRPC_ERROR_UNREF(errors[i]);
+  }
   GPR_TIMER_END("reading_action.parse", 0);
-  grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked,
-                                   (void *)(uintptr_t)success, 0);
+  grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err,
+                                   0);
 }
 
 static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -1699,7 +1764,8 @@
     GPR_ASSERT(stream_global->in_stream_map);
     GPR_ASSERT(stream_global->write_closed);
     GPR_ASSERT(stream_global->read_closed);
-    remove_stream(exec_ctx, t, stream_global->id);
+    remove_stream(exec_ctx, t, stream_global->id,
+                  GRPC_ERROR_CREATE("Stream removed"));
     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
   }
 
@@ -1710,10 +1776,13 @@
                                        grpc_chttp2_transport *t,
                                        grpc_chttp2_stream *s_unused,
                                        void *arg) {
-  bool success = (bool)(uintptr_t)arg;
+  grpc_error *error = arg;
   bool keep_reading = false;
-  if (!success || t->closed) {
-    drop_connection(exec_ctx, t);
+  if (error == GRPC_ERROR_NONE && t->closed) {
+    error = GRPC_ERROR_CREATE("Transport closed");
+  }
+  if (error != GRPC_ERROR_NONE) {
+    drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
     t->endpoint_reading = 0;
     if (!t->executor.writing_active && t->ep) {
       grpc_endpoint_destroy(exec_ctx, t->ep);
@@ -1735,6 +1804,8 @@
   } else {
     UNREF_TRANSPORT(exec_ctx, t, "reading_action");
   }
+
+  GRPC_ERROR_UNREF(error);
 }
 
 /*******************************************************************************
@@ -1743,13 +1814,13 @@
 
 static void connectivity_state_set(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_connectivity_state state, const char *reason) {
+    grpc_connectivity_state state, grpc_error *error, const char *reason) {
   GRPC_CHTTP2_IF_TRACING(
       gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
   grpc_connectivity_state_set(
       exec_ctx,
       &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
-      state, reason);
+      state, error, reason);
 }
 
 /*******************************************************************************
@@ -1795,6 +1866,7 @@
 static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
                                        grpc_chttp2_incoming_byte_stream *bs) {
   if (gpr_unref(&bs->refs)) {
+    GRPC_ERROR_UNREF(bs->error);
     gpr_slice_buffer_destroy(&bs->slices);
     gpr_free(bs);
   }
@@ -1863,9 +1935,10 @@
   }
   if (bs->slices.count > 0) {
     *arg->slice = gpr_slice_buffer_take_first(&bs->slices);
-    grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, true, NULL);
-  } else if (bs->failed) {
-    grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL);
+  } else if (bs->error != GRPC_ERROR_NONE) {
+    grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error),
+                        NULL);
   } else {
     bs->on_next = arg->on_complete;
     bs->next = arg->slice;
@@ -1922,7 +1995,7 @@
   grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream;
   if (bs->on_next != NULL) {
     *bs->next = arg->slice;
-    grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL);
     bs->on_next = NULL;
   } else {
     gpr_slice_buffer_add(&bs->slices, arg->slice);
@@ -1940,13 +2013,30 @@
                                    sizeof(arg));
 }
 
+typedef struct {
+  grpc_chttp2_incoming_byte_stream *bs;
+  grpc_error *error;
+} bs_fail_args;
+
+static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs,
+                                       grpc_error *error) {
+  bs_fail_args *a = gpr_malloc(sizeof(*a));
+  a->bs = bs;
+  a->error = error;
+  return a;
+}
+
 static void incoming_byte_stream_finished_failed_locked(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
     void *argp) {
-  grpc_chttp2_incoming_byte_stream *bs = argp;
-  grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL);
+  bs_fail_args *a = argp;
+  grpc_chttp2_incoming_byte_stream *bs = a->bs;
+  grpc_error *error = a->error;
+  gpr_free(a);
+  grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL);
   bs->on_next = NULL;
-  bs->failed = 1;
+  GRPC_ERROR_UNREF(bs->error);
+  bs->error = error;
   incoming_byte_stream_unref(exec_ctx, bs);
 }
 
@@ -1959,25 +2049,26 @@
 }
 
 void grpc_chttp2_incoming_byte_stream_finished(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
-    int from_parsing_thread) {
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
+    grpc_error *error, int from_parsing_thread) {
   if (from_parsing_thread) {
-    if (success) {
+    if (error == GRPC_ERROR_NONE) {
       grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
                                        incoming_byte_stream_finished_ok_locked,
                                        bs, 0);
     } else {
-      incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
-                                              bs->stream, bs);
-    }
-  } else {
-    if (success) {
       grpc_chttp2_run_with_global_lock(
           exec_ctx, bs->transport, bs->stream,
-          incoming_byte_stream_finished_failed_locked, bs, 0);
+          incoming_byte_stream_finished_failed_locked,
+          make_bs_fail_args(bs, error), 0);
+    }
+  } else {
+    if (error == GRPC_ERROR_NONE) {
+      incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
+                                              bs->stream, bs);
     } else {
-      incoming_byte_stream_finished_failed_locked(exec_ctx, bs->transport,
-                                                  bs->stream, bs);
+      incoming_byte_stream_finished_failed_locked(
+          exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error));
     }
   }
 }
@@ -2000,7 +2091,7 @@
   gpr_slice_buffer_init(&incoming_byte_stream->slices);
   incoming_byte_stream->on_next = NULL;
   incoming_byte_stream->is_tail = 1;
-  incoming_byte_stream->failed = 0;
+  incoming_byte_stream->error = GRPC_ERROR_NONE;
   if (add_to_queue->head == NULL) {
     add_to_queue->head = incoming_byte_stream;
   } else {
@@ -2141,5 +2232,5 @@
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
   REF_TRANSPORT(t, "reading_action"); /* matches unref inside reading_action */
   gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
-  reading_action(exec_ctx, t, 1);
+  reading_action(exec_ctx, t, GRPC_ERROR_NONE);
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame.h b/src/core/ext/transport/chttp2/transport/frame.h
index 5c72d91..7776609 100644
--- a/src/core/ext/transport/chttp2/transport/frame.h
+++ b/src/core/ext/transport/chttp2/transport/frame.h
@@ -37,13 +37,7 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/slice.h>
 
-/* Common definitions for frame handling in the chttp2 transport */
-
-typedef enum {
-  GRPC_CHTTP2_PARSE_OK,
-  GRPC_CHTTP2_STREAM_ERROR,
-  GRPC_CHTTP2_CONNECTION_ERROR
-} grpc_chttp2_parse_error;
+#include "src/core/lib/iomgr/error.h"
 
 /* defined in internal.h */
 typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing;
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c
index 3a6d80e..9046fbc 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.c
+++ b/src/core/ext/transport/chttp2/transport/frame_data.c
@@ -37,24 +37,25 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 #include "src/core/ext/transport/chttp2/transport/internal.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/transport.h"
 
-grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
-    grpc_chttp2_data_parser *parser) {
+grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser) {
   parser->state = GRPC_CHTTP2_DATA_FH_0;
   parser->parsing_frame = NULL;
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
 void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
                                      grpc_chttp2_data_parser *parser) {
   grpc_byte_stream *bs;
   if (parser->parsing_frame) {
-    grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
-                                              0, 1);
+    grpc_chttp2_incoming_byte_stream_finished(
+        exec_ctx, parser->parsing_frame, GRPC_ERROR_CREATE("Parser destroyed"),
+        1);
   }
   while (
       (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
@@ -62,11 +63,16 @@
   }
 }
 
-grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
-    grpc_chttp2_data_parser *parser, uint8_t flags) {
+grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
+                                                uint8_t flags,
+                                                uint32_t stream_id) {
   if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
-    gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
-    return GRPC_CHTTP2_STREAM_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "unsupported data flags: 0x%02x", flags);
+    grpc_error *err = grpc_error_set_int(
+        GRPC_ERROR_CREATE(msg), GRPC_ERROR_INT_STREAM_ID, (intptr_t)stream_id);
+    gpr_free(msg);
+    return err;
   }
 
   if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
@@ -75,7 +81,7 @@
     parser->is_last_frame = 0;
   }
 
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
 void grpc_chttp2_incoming_frame_queue_merge(
@@ -139,7 +145,7 @@
   stats->data_bytes += write_bytes;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
+grpc_error *grpc_chttp2_data_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -149,19 +155,20 @@
   grpc_chttp2_data_parser *p = parser;
   uint32_t message_flags;
   grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
+  char *msg;
 
   if (is_last && p->is_last_frame) {
     stream_parsing->received_close = 1;
   }
 
   if (cur == end) {
-    return GRPC_CHTTP2_PARSE_OK;
+    return GRPC_ERROR_NONE;
   }
 
   switch (p->state) {
     case GRPC_CHTTP2_DATA_ERROR:
       p->state = GRPC_CHTTP2_DATA_ERROR;
-      return GRPC_CHTTP2_STREAM_ERROR;
+      return GRPC_ERROR_REF(p->error);
     fh_0:
     case GRPC_CHTTP2_DATA_FH_0:
       stream_parsing->stats.incoming.framing_bytes++;
@@ -174,13 +181,23 @@
           p->is_frame_compressed = 1; /* GPR_TRUE */
           break;
         default:
-          gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
+          gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type);
+          p->error = GRPC_ERROR_CREATE(msg);
+          p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
+                                        (intptr_t)stream_parsing->id);
+          gpr_free(msg);
+          msg = gpr_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+          p->error =
+              grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, msg);
+          gpr_free(msg);
+          p->error =
+              grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
           p->state = GRPC_CHTTP2_DATA_ERROR;
-          return GRPC_CHTTP2_STREAM_ERROR;
+          return GRPC_ERROR_REF(p->error);
       }
       if (++cur == end) {
         p->state = GRPC_CHTTP2_DATA_FH_1;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_CHTTP2_DATA_FH_1:
@@ -188,7 +205,7 @@
       p->frame_size = ((uint32_t)*cur) << 24;
       if (++cur == end) {
         p->state = GRPC_CHTTP2_DATA_FH_2;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_CHTTP2_DATA_FH_2:
@@ -196,7 +213,7 @@
       p->frame_size |= ((uint32_t)*cur) << 16;
       if (++cur == end) {
         p->state = GRPC_CHTTP2_DATA_FH_3;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_CHTTP2_DATA_FH_3:
@@ -204,7 +221,7 @@
       p->frame_size |= ((uint32_t)*cur) << 8;
       if (++cur == end) {
         p->state = GRPC_CHTTP2_DATA_FH_4;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_CHTTP2_DATA_FH_4:
@@ -225,7 +242,7 @@
       grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                                                stream_parsing);
       if (cur == end) {
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       uint32_t remaining = (uint32_t)(end - cur);
       if (remaining == p->frame_size) {
@@ -233,19 +250,19 @@
         grpc_chttp2_incoming_byte_stream_push(
             exec_ctx, p->parsing_frame,
             gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
-        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
-                                                  1);
+        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
+                                                  GRPC_ERROR_NONE, 1);
         p->parsing_frame = NULL;
         p->state = GRPC_CHTTP2_DATA_FH_0;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       } else if (remaining > p->frame_size) {
         stream_parsing->stats.incoming.data_bytes += p->frame_size;
         grpc_chttp2_incoming_byte_stream_push(
             exec_ctx, p->parsing_frame,
             gpr_slice_sub(slice, (size_t)(cur - beg),
                           (size_t)(cur + p->frame_size - beg)));
-        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
-                                                  1);
+        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
+                                                  GRPC_ERROR_NONE, 1);
         p->parsing_frame = NULL;
         cur += p->frame_size;
         goto fh_0; /* loop */
@@ -256,9 +273,9 @@
             gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
         p->frame_size -= remaining;
         stream_parsing->stats.incoming.data_bytes += remaining;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
   }
 
-  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
+  GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h
index af71f48..a21a794 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.h
+++ b/src/core/ext/transport/chttp2/transport/frame_data.h
@@ -66,6 +66,7 @@
   uint8_t is_last_frame;
   uint8_t frame_type;
   uint32_t frame_size;
+  grpc_error *error;
 
   int is_frame_compressed;
   grpc_chttp2_incoming_frame_queue incoming_frames;
@@ -79,19 +80,19 @@
     grpc_chttp2_incoming_frame_queue *q);
 
 /* initialize per-stream state for data frame parsing */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
-    grpc_chttp2_data_parser *parser);
+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);
 
 /* start processing a new data frame */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
-    grpc_chttp2_data_parser *parser, uint8_t flags);
+grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
+                                                uint8_t flags,
+                                                uint32_t stream_id);
 
 /* handle a slice of a data frame - is_last indicates the last slice of a
    frame */
-grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
+grpc_error *grpc_chttp2_data_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.c b/src/core/ext/transport/chttp2/transport/frame_goaway.c
index 827e7a6..299e27a 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.c
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.c
@@ -38,6 +38,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
   p->debug_data = NULL;
@@ -47,11 +48,15 @@
   gpr_free(p->debug_data);
 }
 
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
-    grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
+grpc_error *grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser *p,
+                                                  uint32_t length,
+                                                  uint8_t flags) {
   if (length < 8) {
-    gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "goaway frame too short (%d bytes)", length);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
 
   gpr_free(p->debug_data);
@@ -59,10 +64,10 @@
   p->debug_data = gpr_malloc(p->debug_length);
   p->debug_pos = 0;
   p->state = GRPC_CHTTP2_GOAWAY_LSI0;
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
+grpc_error *grpc_chttp2_goaway_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -75,7 +80,7 @@
     case GRPC_CHTTP2_GOAWAY_LSI0:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_LSI0;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->last_stream_id = ((uint32_t)*cur) << 24;
       ++cur;
@@ -83,7 +88,7 @@
     case GRPC_CHTTP2_GOAWAY_LSI1:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_LSI1;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->last_stream_id |= ((uint32_t)*cur) << 16;
       ++cur;
@@ -91,7 +96,7 @@
     case GRPC_CHTTP2_GOAWAY_LSI2:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_LSI2;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->last_stream_id |= ((uint32_t)*cur) << 8;
       ++cur;
@@ -99,7 +104,7 @@
     case GRPC_CHTTP2_GOAWAY_LSI3:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_LSI3;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->last_stream_id |= ((uint32_t)*cur);
       ++cur;
@@ -107,7 +112,7 @@
     case GRPC_CHTTP2_GOAWAY_ERR0:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_ERR0;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->error_code = ((uint32_t)*cur) << 24;
       ++cur;
@@ -115,7 +120,7 @@
     case GRPC_CHTTP2_GOAWAY_ERR1:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_ERR1;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->error_code |= ((uint32_t)*cur) << 16;
       ++cur;
@@ -123,7 +128,7 @@
     case GRPC_CHTTP2_GOAWAY_ERR2:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_ERR2;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->error_code |= ((uint32_t)*cur) << 8;
       ++cur;
@@ -131,7 +136,7 @@
     case GRPC_CHTTP2_GOAWAY_ERR3:
       if (cur == end) {
         p->state = GRPC_CHTTP2_GOAWAY_ERR3;
-        return GRPC_CHTTP2_PARSE_OK;
+        return GRPC_ERROR_NONE;
       }
       p->error_code |= ((uint32_t)*cur);
       ++cur;
@@ -151,9 +156,9 @@
             gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
         p->debug_data = NULL;
       }
-      return GRPC_CHTTP2_PARSE_OK;
+      return GRPC_ERROR_NONE;
   }
-  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
+  GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
 }
 
 void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.h b/src/core/ext/transport/chttp2/transport/frame_goaway.h
index 7c38b26..eb43034 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.h
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.h
@@ -63,9 +63,9 @@
 
 void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p);
 void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
+grpc_error *grpc_chttp2_goaway_parser_begin_frame(
     grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
+grpc_error *grpc_chttp2_goaway_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c
index 7e1815f..1f814ab 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.c
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -38,6 +38,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
   gpr_slice slice = gpr_slice_malloc(9 + 8);
@@ -57,18 +58,22 @@
   return slice;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
-    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) {
+grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
+                                                uint32_t length,
+                                                uint8_t flags) {
   if (flags & 0xfe || length != 8) {
-    gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "invalid ping: length=%d, flags=%02x", length, flags);
+    grpc_error *error = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return error;
   }
   parser->byte = 0;
   parser->is_ack = flags;
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
+grpc_error *grpc_chttp2_ping_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -93,5 +98,5 @@
     }
   }
 
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h
index 4f7fcc1..5a87234 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.h
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.h
@@ -46,9 +46,9 @@
 
 gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
 
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
-    grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
+grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
+                                                uint32_t length, uint8_t flags);
+grpc_error *grpc_chttp2_ping_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
index 7f01105..a7aefb9 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
@@ -34,7 +34,9 @@
 #include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
 #include "src/core/ext/transport/chttp2/transport/internal.h"
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 
@@ -67,18 +69,21 @@
   return slice;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
+grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
     grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) {
   if (length != 4) {
-    gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
-            flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "invalid rst_stream: length=%d, flags=%02x", length,
+                 flags);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
   parser->byte = 0;
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
+grpc_error *grpc_chttp2_rst_stream_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -97,12 +102,13 @@
   if (p->byte == 4) {
     GPR_ASSERT(is_last);
     stream_parsing->received_close = 1;
-    stream_parsing->saw_rst_stream = 1;
-    stream_parsing->rst_stream_reason = (((uint32_t)p->reason_bytes[0]) << 24) |
-                                        (((uint32_t)p->reason_bytes[1]) << 16) |
-                                        (((uint32_t)p->reason_bytes[2]) << 8) |
-                                        (((uint32_t)p->reason_bytes[3]));
+    stream_parsing->forced_close_error = grpc_error_set_int(
+        GRPC_ERROR_CREATE("RST_STREAM"), GRPC_ERROR_INT_HTTP2_ERROR,
+        (intptr_t)((((uint32_t)p->reason_bytes[0]) << 24) |
+                   (((uint32_t)p->reason_bytes[1]) << 16) |
+                   (((uint32_t)p->reason_bytes[2]) << 8) |
+                   (((uint32_t)p->reason_bytes[3]))));
   }
 
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
index 9c1e756..11cf94f 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
@@ -47,9 +47,9 @@
 gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
                                         grpc_transport_one_way_stats *stats);
 
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
+grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
     grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
+grpc_error *grpc_chttp2_rst_stream_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
index a3c1e15..04b96c4 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.c
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -36,7 +36,9 @@
 
 #include <string.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
@@ -118,7 +120,7 @@
   return output;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
+grpc_error *grpc_chttp2_settings_parser_begin_frame(
     grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
     uint32_t *settings) {
   parser->target_settings = settings;
@@ -129,31 +131,29 @@
   if (flags == GRPC_CHTTP2_FLAG_ACK) {
     parser->is_ack = 1;
     if (length != 0) {
-      gpr_log(GPR_ERROR, "non-empty settings ack frame received");
-      return GRPC_CHTTP2_CONNECTION_ERROR;
+      return GRPC_ERROR_CREATE("non-empty settings ack frame received");
     }
-    return GRPC_CHTTP2_PARSE_OK;
+    return GRPC_ERROR_NONE;
   } else if (flags != 0) {
-    gpr_log(GPR_ERROR, "invalid flags on settings frame");
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    return GRPC_ERROR_CREATE("invalid flags on settings frame");
   } else if (length % 6 != 0) {
-    gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes");
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    return GRPC_ERROR_CREATE("settings frames must be a multiple of six bytes");
   } else {
-    return GRPC_CHTTP2_PARSE_OK;
+    return GRPC_ERROR_NONE;
   }
 }
 
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
+grpc_error *grpc_chttp2_settings_parser_parse(
     grpc_exec_ctx *exec_ctx, void *p,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
   grpc_chttp2_settings_parser *parser = p;
   const uint8_t *cur = GPR_SLICE_START_PTR(slice);
   const uint8_t *end = GPR_SLICE_END_PTR(slice);
+  char *msg;
 
   if (parser->is_ack) {
-    return GRPC_CHTTP2_PARSE_OK;
+    return GRPC_ERROR_NONE;
   }
 
   for (;;) {
@@ -168,7 +168,7 @@
             gpr_slice_buffer_add(&transport_parsing->qbuf,
                                  grpc_chttp2_settings_ack_create());
           }
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         }
         parser->id = (uint16_t)(((uint16_t)*cur) << 8);
         cur++;
@@ -176,7 +176,7 @@
       case GRPC_CHTTP2_SPS_ID1:
         if (cur == end) {
           parser->state = GRPC_CHTTP2_SPS_ID1;
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         }
         parser->id = (uint16_t)(parser->id | (*cur));
         cur++;
@@ -184,7 +184,7 @@
       case GRPC_CHTTP2_SPS_VAL0:
         if (cur == end) {
           parser->state = GRPC_CHTTP2_SPS_VAL0;
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         }
         parser->value = ((uint32_t)*cur) << 24;
         cur++;
@@ -192,7 +192,7 @@
       case GRPC_CHTTP2_SPS_VAL1:
         if (cur == end) {
           parser->state = GRPC_CHTTP2_SPS_VAL1;
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         }
         parser->value |= ((uint32_t)*cur) << 16;
         cur++;
@@ -200,7 +200,7 @@
       case GRPC_CHTTP2_SPS_VAL2:
         if (cur == end) {
           parser->state = GRPC_CHTTP2_SPS_VAL2;
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         }
         parser->value |= ((uint32_t)*cur) << 8;
         cur++;
@@ -208,7 +208,7 @@
       case GRPC_CHTTP2_SPS_VAL3:
         if (cur == end) {
           parser->state = GRPC_CHTTP2_SPS_VAL3;
-          return GRPC_CHTTP2_PARSE_OK;
+          return GRPC_ERROR_NONE;
         } else {
           parser->state = GRPC_CHTTP2_SPS_ID0;
         }
@@ -229,9 +229,11 @@
                     transport_parsing->last_incoming_stream_id, sp->error_value,
                     gpr_slice_from_static_string("HTTP2 settings error"),
                     &transport_parsing->qbuf);
-                gpr_log(GPR_ERROR, "invalid value %u passed for %s",
-                        parser->value, sp->name);
-                return GRPC_CHTTP2_CONNECTION_ERROR;
+                gpr_asprintf(&msg, "invalid value %u passed for %s",
+                             parser->value, sp->name);
+                grpc_error *err = GRPC_ERROR_CREATE(msg);
+                gpr_free(msg);
+                return err;
             }
           }
           if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
@@ -249,7 +251,7 @@
                     transport_parsing->is_client ? "CLI" : "SVR", parser->id,
                     parser->value);
           }
-        } else {
+        } else if (grpc_http_trace) {
           gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
                   parser->id, parser->value);
         }
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index d9e30f1..f654c59 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -92,10 +92,10 @@
 /* Create an ack settings frame */
 gpr_slice grpc_chttp2_settings_ack_create(void);
 
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
+grpc_error *grpc_chttp2_settings_parser_begin_frame(
     grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
     uint32_t *settings);
-grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
+grpc_error *grpc_chttp2_settings_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c
index 9024341..3cf848f 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.c
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c
@@ -34,7 +34,9 @@
 #include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
 #include "src/core/ext/transport/chttp2/transport/internal.h"
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 gpr_slice grpc_chttp2_window_update_create(
     uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) {
@@ -62,19 +64,22 @@
   return slice;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
+grpc_error *grpc_chttp2_window_update_parser_begin_frame(
     grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) {
   if (flags || length != 4) {
-    gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length,
-            flags);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "invalid window update: length=%d, flags=%02x", length,
+                 flags);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
   parser->byte = 0;
   parser->amount = 0;
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
+grpc_error *grpc_chttp2_window_update_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -96,8 +101,11 @@
   if (p->byte == 4) {
     uint32_t received_update = p->amount;
     if (received_update == 0 || (received_update & 0x80000000u)) {
-      gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount);
-      return GRPC_CHTTP2_CONNECTION_ERROR;
+      char *msg;
+      gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount);
+      grpc_error *err = GRPC_ERROR_CREATE(msg);
+      gpr_free(msg);
+      return err;
     }
     GPR_ASSERT(is_last);
 
@@ -115,5 +123,5 @@
     }
   }
 
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h
index d6e87b9..1bcbbf9 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.h
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h
@@ -48,9 +48,9 @@
 gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta,
                                            grpc_transport_one_way_stats *stats);
 
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
+grpc_error *grpc_chttp2_window_update_parser_begin_frame(
     grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags);
-grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
+grpc_error *grpc_chttp2_window_update_parser_parse(
     grpc_exec_ctx *exec_ctx, void *parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index ed45bc9..522455f 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -46,6 +46,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
 #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
@@ -77,63 +78,70 @@
    a set of indirect jumps, and so not waste stack space. */
 
 /* forward declarations for parsing states */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end);
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end);
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end);
+static grpc_error *parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end);
+static grpc_error *parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end, grpc_error *error);
+static grpc_error *still_parse_error(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_illegal_op(grpc_chttp2_hpack_parser *p,
+                                    const uint8_t *cur, const uint8_t *end);
 
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end);
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end);
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end);
+static grpc_error *parse_string_prefix(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_key_string(grpc_chttp2_hpack_parser *p,
+                                    const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_value_string_with_indexed_key(
+    grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_value_string_with_literal_key(
+    grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end);
 
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end);
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end);
-
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end);
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end);
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end);
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+static grpc_error *parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
                                 const uint8_t *end);
+static grpc_error *parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end);
+static grpc_error *parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end);
+static grpc_error *parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end);
+static grpc_error *parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end);
+static grpc_error *parse_value5up(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end);
+
+static grpc_error *parse_indexed_field(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end);
+static grpc_error *parse_max_tbl_size(grpc_chttp2_hpack_parser *p,
+                                      const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur, const uint8_t *end);
 
 /* we translate the first byte of a hpack field into one of these decoding
    cases, then use a lookup table to jump directly to the appropriate parser.
@@ -631,19 +639,18 @@
 };
 
 /* emission helpers */
-static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
-                  int add_to_table) {
+static grpc_error *on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
+                          int add_to_table) {
   if (add_to_table) {
-    if (!grpc_chttp2_hptbl_add(&p->table, md)) {
-      return 0;
-    }
+    grpc_error *err = grpc_chttp2_hptbl_add(&p->table, md);
+    if (err != GRPC_ERROR_NONE) return err;
   }
   if (p->on_header == NULL) {
     GRPC_MDELEM_UNREF(md);
-    return 0;
+    return GRPC_ERROR_CREATE("on_header callback not set");
   }
   p->on_header(p->on_header_user_data, md);
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
@@ -654,70 +661,70 @@
 }
 
 /* jump to the next state */
-static int parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                      const uint8_t *end) {
+static grpc_error *parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end) {
   p->state = *p->next_state++;
   return p->state(p, cur, end);
 }
 
 /* begin parsing a header: all functionality is encoded into lookup tables
    above */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end) {
+static grpc_error *parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end) {
   if (cur == end) {
     p->state = parse_begin;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return first_byte_action[first_byte_lut[*cur]](p, cur, end);
 }
 
 /* stream dependency and prioritization data: we just skip it */
-static int parse_stream_weight(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_stream_weight(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_stream_weight;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return p->after_prioritization(p, cur + 1, end);
 }
 
-static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
+static grpc_error *parse_stream_dep3(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_stream_dep3;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return parse_stream_weight(p, cur + 1, end);
 }
 
-static int parse_stream_dep2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
+static grpc_error *parse_stream_dep2(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_stream_dep2;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return parse_stream_dep3(p, cur + 1, end);
 }
 
-static int parse_stream_dep1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
+static grpc_error *parse_stream_dep1(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_stream_dep1;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return parse_stream_dep2(p, cur + 1, end);
 }
 
-static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                             const uint8_t *end) {
+static grpc_error *parse_stream_dep0(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_stream_dep0;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   return parse_stream_dep1(p, cur + 1, end);
@@ -725,30 +732,34 @@
 
 /* emit an indexed field; for now just logs it to console; jumps to
    begin the next field on completion */
-static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
+static grpc_error *finish_indexed_field(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur,
+                                        const uint8_t *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
   if (md == NULL) {
-    if (grpc_http_trace) {
-      gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
-    }
-    return 0;
+    return grpc_error_set_int(
+        grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
+                           GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
+        GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
   }
   GRPC_MDELEM_REF(md);
-  return on_hdr(p, md, 0) && parse_begin(p, cur, end);
+  grpc_error *err = on_hdr(p, md, 0);
+  if (err != GRPC_ERROR_NONE) return err;
+  return parse_begin(p, cur, end);
 }
 
 /* parse an indexed field with index < 127 */
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_indexed_field(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   p->dynamic_table_update_allowed = 0;
   p->index = (*cur) & 0x7f;
   return finish_indexed_field(p, cur + 1, end);
 }
 
 /* parse an indexed field with index >= 127 */
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       finish_indexed_field};
   p->dynamic_table_update_allowed = 0;
@@ -760,28 +771,34 @@
 
 /* finish a literal header with incremental indexing: just log, and jump to '
    begin */
-static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
+static grpc_error *finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur,
+                                        const uint8_t *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
   GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                1) &&
-         parse_begin(p, cur, end);
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                  take_string(p, &p->value)),
+             1);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* finish a literal header with incremental indexing with no index */
-static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                1) &&
-         parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                          const uint8_t *cur,
+                                          const uint8_t *end) {
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                  take_string(p, &p->value)),
+             1);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* parse a literal header with incremental indexing; index < 63 */
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_value_string_with_indexed_key, finish_lithdr_incidx};
   p->dynamic_table_update_allowed = 0;
@@ -791,8 +808,9 @@
 }
 
 /* parse a literal header with incremental indexing; index >= 63 */
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_string_prefix, parse_value_string_with_indexed_key,
       finish_lithdr_incidx};
@@ -804,8 +822,9 @@
 }
 
 /* parse a literal header with incremental indexing; index = 0 */
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_key_string, parse_string_prefix,
       parse_value_string_with_literal_key, finish_lithdr_incidx_v};
@@ -815,28 +834,34 @@
 }
 
 /* finish a literal header without incremental indexing */
-static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
+static grpc_error *finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur,
+                                        const uint8_t *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
   GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                  take_string(p, &p->value)),
+             0);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* finish a literal header without incremental indexing with index = 0 */
-static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                          const uint8_t *cur,
+                                          const uint8_t *end) {
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                  take_string(p, &p->value)),
+             0);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* parse a literal header without incremental indexing; index < 15 */
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_value_string_with_indexed_key, finish_lithdr_notidx};
   p->dynamic_table_update_allowed = 0;
@@ -846,8 +871,9 @@
 }
 
 /* parse a literal header without incremental indexing; index >= 15 */
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_string_prefix, parse_value_string_with_indexed_key,
       finish_lithdr_notidx};
@@ -859,8 +885,9 @@
 }
 
 /* parse a literal header without incremental indexing; index == 0 */
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_key_string, parse_string_prefix,
       parse_value_string_with_literal_key, finish_lithdr_notidx_v};
@@ -870,28 +897,34 @@
 }
 
 /* finish a literal header that is never indexed */
-static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
+static grpc_error *finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur,
+                                        const uint8_t *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
   GPR_ASSERT(md != NULL); /* handled in string parsing */
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+                                                  take_string(p, &p->value)),
+             0);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* finish a literal header that is never indexed with an extra value */
-static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                  const uint8_t *cur, const uint8_t *end) {
-  return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
-                                                     take_string(p, &p->value)),
-                0) &&
-         parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                          const uint8_t *cur,
+                                          const uint8_t *end) {
+  grpc_error *err =
+      on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+                                                  take_string(p, &p->value)),
+             0);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* parse a literal header that is never indexed; index < 15 */
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_value_string_with_indexed_key, finish_lithdr_nvridx};
   p->dynamic_table_update_allowed = 0;
@@ -901,8 +934,9 @@
 }
 
 /* parse a literal header that is never indexed; index >= 15 */
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_string_prefix, parse_value_string_with_indexed_key,
       finish_lithdr_nvridx};
@@ -914,8 +948,9 @@
 }
 
 /* parse a literal header that is never indexed; index == 0 */
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
-                                 const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+                                         const uint8_t *cur,
+                                         const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       parse_key_string, parse_string_prefix,
       parse_value_string_with_literal_key, finish_lithdr_nvridx_v};
@@ -925,20 +960,25 @@
 }
 
 /* finish parsing a max table size change */
-static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *finish_max_tbl_size(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   if (grpc_http_trace) {
     gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
   }
-  return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
-         parse_begin(p, cur, end);
+  grpc_error *err =
+      grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_begin(p, cur, end);
 }
 
 /* parse a max table size change, max size < 15 */
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end) {
+static grpc_error *parse_max_tbl_size(grpc_chttp2_hpack_parser *p,
+                                      const uint8_t *cur, const uint8_t *end) {
   if (p->dynamic_table_update_allowed == 0) {
-    return 0;
+    return parse_error(
+        p, cur, end,
+        GRPC_ERROR_CREATE(
+            "More than two max table size changes in a single frame"));
   }
   p->dynamic_table_update_allowed--;
   p->index = (*cur) & 0x1f;
@@ -946,12 +986,16 @@
 }
 
 /* parse a max table size change, max size >= 15 */
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                                const uint8_t *end) {
+static grpc_error *parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
+                                        const uint8_t *cur,
+                                        const uint8_t *end) {
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       finish_max_tbl_size};
   if (p->dynamic_table_update_allowed == 0) {
-    return 0;
+    return parse_error(
+        p, cur, end,
+        GRPC_ERROR_CREATE(
+            "More than two max table size changes in a single frame"));
   }
   p->dynamic_table_update_allowed--;
   p->next_state = and_then;
@@ -961,28 +1005,38 @@
 }
 
 /* a parse error: jam the parse state into parse_error, and return error */
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                       const uint8_t *end) {
-  p->state = parse_error;
-  return 0;
+static grpc_error *parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                               const uint8_t *end, grpc_error *err) {
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
+  if (p->last_error == GRPC_ERROR_NONE) {
+    p->last_error = GRPC_ERROR_REF(err);
+  }
+  p->state = still_parse_error;
+  return err;
 }
 
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end) {
+static grpc_error *still_parse_error(grpc_chttp2_hpack_parser *p,
+                                     const uint8_t *cur, const uint8_t *end) {
+  return GRPC_ERROR_REF(p->last_error);
+}
+
+static grpc_error *parse_illegal_op(grpc_chttp2_hpack_parser *p,
+                                    const uint8_t *cur, const uint8_t *end) {
   GPR_ASSERT(cur != end);
-  if (grpc_http_trace) {
-    gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
-  }
-  return parse_error(p, cur, end);
+  char *msg;
+  gpr_asprintf(&msg, "Illegal hpack op code %d", *cur);
+  grpc_error *err = GRPC_ERROR_CREATE(msg);
+  gpr_free(msg);
+  return parse_error(p, cur, end, err);
 }
 
 /* parse the 1st byte of a varint into p->parsing.value
    no overflow is possible */
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   if (cur == end) {
     p->state = parse_value0;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   *p->parsing.value += (*cur) & 0x7f;
@@ -996,11 +1050,11 @@
 
 /* parse the 2nd byte of a varint into p->parsing.value
    no overflow is possible */
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   if (cur == end) {
     p->state = parse_value1;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7;
@@ -1014,11 +1068,11 @@
 
 /* parse the 3rd byte of a varint into p->parsing.value
    no overflow is possible */
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   if (cur == end) {
     p->state = parse_value2;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14;
@@ -1032,11 +1086,11 @@
 
 /* parse the 4th byte of a varint into p->parsing.value
    no overflow is possible */
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   if (cur == end) {
     p->state = parse_value3;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   *p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21;
@@ -1050,15 +1104,16 @@
 
 /* parse the 5th byte of a varint into p->parsing.value
    depending on the byte, we may overflow, and care must be taken */
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   uint8_t c;
   uint32_t cur_value;
   uint32_t add_value;
+  char *msg;
 
   if (cur == end) {
     p->state = parse_value4;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   c = (*cur) & 0x7f;
@@ -1081,48 +1136,49 @@
   }
 
 error:
-  if (grpc_http_trace) {
-    gpr_log(GPR_ERROR,
-            "integer overflow in hpack integer decoding: have 0x%08x, "
-            "got byte 0x%02x on byte 5",
-            *p->parsing.value, *cur);
-  }
-  return parse_error(p, cur, end);
+  gpr_asprintf(&msg,
+               "integer overflow in hpack integer decoding: have 0x%08x, "
+               "got byte 0x%02x on byte 5",
+               *p->parsing.value, *cur);
+  grpc_error *err = GRPC_ERROR_CREATE(msg);
+  gpr_free(msg);
+  return parse_error(p, cur, end, err);
 }
 
 /* parse any trailing bytes in a varint: it's possible to append an arbitrary
    number of 0x80's and not affect the value - a zero will terminate - and
    anything else will overflow */
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end) {
+static grpc_error *parse_value5up(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end) {
   while (cur != end && *cur == 0x80) {
     ++cur;
   }
 
   if (cur == end) {
     p->state = parse_value5up;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   if (*cur == 0) {
     return parse_next(p, cur + 1, end);
   }
 
-  if (grpc_http_trace) {
-    gpr_log(GPR_ERROR,
-            "integer overflow in hpack integer decoding: have 0x%08x, "
-            "got byte 0x%02x sometime after byte 5",
-            *p->parsing.value, *cur);
-  }
-  return parse_error(p, cur, end);
+  char *msg;
+  gpr_asprintf(&msg,
+               "integer overflow in hpack integer decoding: have 0x%08x, "
+               "got byte 0x%02x sometime after byte 5",
+               *p->parsing.value, *cur);
+  grpc_error *err = GRPC_ERROR_CREATE(msg);
+  gpr_free(msg);
+  return parse_error(p, cur, end, err);
 }
 
 /* parse a string prefix */
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                               const uint8_t *end) {
+static grpc_error *parse_string_prefix(grpc_chttp2_hpack_parser *p,
+                                       const uint8_t *cur, const uint8_t *end) {
   if (cur == end) {
     p->state = parse_string_prefix;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   p->strlen = (*cur) & 0x7f;
@@ -1149,25 +1205,26 @@
   str->length += (uint32_t)length;
 }
 
-static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                         const uint8_t *end) {
+static grpc_error *append_string(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
   grpc_chttp2_hpack_parser_string *str = p->parsing.str;
   uint32_t bits;
   uint8_t decoded[3];
   switch ((binary_state)p->binary) {
     case NOT_BINARY:
       append_bytes(str, cur, (size_t)(end - cur));
-      return 1;
+      return GRPC_ERROR_NONE;
     b64_byte0:
     case B64_BYTE0:
       if (cur == end) {
         p->binary = B64_BYTE0;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       bits = inverse_base64[*cur];
       ++cur;
       if (bits == 255)
-        return 0;
+        return parse_error(p, cur, end,
+                           GRPC_ERROR_CREATE("Illegal base64 character"));
       else if (bits == 64)
         goto b64_byte0;
       p->base64_buffer = bits << 18;
@@ -1176,12 +1233,13 @@
     case B64_BYTE1:
       if (cur == end) {
         p->binary = B64_BYTE1;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       bits = inverse_base64[*cur];
       ++cur;
       if (bits == 255)
-        return 0;
+        return parse_error(p, cur, end,
+                           GRPC_ERROR_CREATE("Illegal base64 character"));
       else if (bits == 64)
         goto b64_byte1;
       p->base64_buffer |= bits << 12;
@@ -1190,12 +1248,13 @@
     case B64_BYTE2:
       if (cur == end) {
         p->binary = B64_BYTE2;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       bits = inverse_base64[*cur];
       ++cur;
       if (bits == 255)
-        return 0;
+        return parse_error(p, cur, end,
+                           GRPC_ERROR_CREATE("Illegal base64 character"));
       else if (bits == 64)
         goto b64_byte2;
       p->base64_buffer |= bits << 6;
@@ -1204,12 +1263,13 @@
     case B64_BYTE3:
       if (cur == end) {
         p->binary = B64_BYTE3;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       bits = inverse_base64[*cur];
       ++cur;
       if (bits == 255)
-        return 0;
+        return parse_error(p, cur, end,
+                           GRPC_ERROR_CREATE("Illegal base64 character"));
       else if (bits == 64)
         goto b64_byte3;
       p->base64_buffer |= bits;
@@ -1220,11 +1280,13 @@
       append_bytes(str, decoded, 3);
       goto b64_byte0;
   }
-  GPR_UNREACHABLE_CODE(return 1);
+  GPR_UNREACHABLE_CODE(return parse_error(
+      p, cur, end, GRPC_ERROR_CREATE("Should never reach here")));
 }
 
 /* append a null terminator to a string */
-static int finish_str(grpc_chttp2_hpack_parser *p) {
+static grpc_error *finish_str(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                              const uint8_t *end) {
   uint8_t terminator = 0;
   uint8_t decoded[2];
   uint32_t bits;
@@ -1235,14 +1297,18 @@
     case B64_BYTE0:
       break;
     case B64_BYTE1:
-      gpr_log(GPR_ERROR, "illegal base64 encoding");
-      return 0; /* illegal encoding */
+      return parse_error(
+          p, cur, end,
+          GRPC_ERROR_CREATE("illegal base64 encoding")); /* illegal encoding */
     case B64_BYTE2:
       bits = p->base64_buffer;
       if (bits & 0xffff) {
-        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%04x",
-                bits & 0xffff);
-        return 0;
+        char *msg;
+        gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%04x",
+                     bits & 0xffff);
+        grpc_error *err = GRPC_ERROR_CREATE(msg);
+        gpr_free(msg);
+        return parse_error(p, cur, end, err);
       }
       decoded[0] = (uint8_t)(bits >> 16);
       append_bytes(str, decoded, 1);
@@ -1250,9 +1316,12 @@
     case B64_BYTE3:
       bits = p->base64_buffer;
       if (bits & 0xff) {
-        gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%02x",
-                bits & 0xff);
-        return 0;
+        char *msg;
+        gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%02x",
+                     bits & 0xff);
+        grpc_error *err = GRPC_ERROR_CREATE(msg);
+        gpr_free(msg);
+        return parse_error(p, cur, end, err);
       }
       decoded[0] = (uint8_t)(bits >> 16);
       decoded[1] = (uint8_t)(bits >> 8);
@@ -1261,38 +1330,42 @@
   }
   append_bytes(str, &terminator, 1);
   p->parsing.str->length--; /* don't actually count the null terminator */
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 /* decode a nibble from a huffman encoded stream */
-static int huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
+static grpc_error *huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
   int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble];
   int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble];
   if (emit != -1) {
     if (emit >= 0 && emit < 256) {
       uint8_t c = (uint8_t)emit;
-      if (!append_string(p, &c, (&c) + 1)) return 0;
+      grpc_error *err = append_string(p, &c, (&c) + 1);
+      if (err != GRPC_ERROR_NONE) return err;
     } else {
       assert(emit == 256);
     }
   }
   p->huff_state = next;
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 /* decode full bytes from a huffman encoded stream */
-static int add_huff_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                          const uint8_t *end) {
+static grpc_error *add_huff_bytes(grpc_chttp2_hpack_parser *p,
+                                  const uint8_t *cur, const uint8_t *end) {
   for (; cur != end; ++cur) {
-    if (!huff_nibble(p, *cur >> 4) || !huff_nibble(p, *cur & 0xf)) return 0;
+    grpc_error *err = huff_nibble(p, *cur >> 4);
+    if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+    err = huff_nibble(p, *cur & 0xf);
+    if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
   }
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 /* decode some string bytes based on the current decoding mode
    (huffman or not) */
-static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                         const uint8_t *end) {
+static grpc_error *add_str_bytes(grpc_chttp2_hpack_parser *p,
+                                 const uint8_t *cur, const uint8_t *end) {
   if (p->huff) {
     return add_huff_bytes(p, cur, end);
   } else {
@@ -1301,26 +1374,31 @@
 }
 
 /* parse a string - tries to do large chunks at a time */
-static int parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                        const uint8_t *end) {
+static grpc_error *parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+                                const uint8_t *end) {
   size_t remaining = p->strlen - p->strgot;
   size_t given = (size_t)(end - cur);
   if (remaining <= given) {
-    return add_str_bytes(p, cur, cur + remaining) && finish_str(p) &&
-           parse_next(p, cur + remaining, end);
+    grpc_error *err = add_str_bytes(p, cur, cur + remaining);
+    if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+    err = finish_str(p, cur + remaining, end);
+    if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+    return parse_next(p, cur + remaining, end);
   } else {
-    if (!add_str_bytes(p, cur, cur + given)) return 0;
+    grpc_error *err = add_str_bytes(p, cur, cur + given);
+    if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
     GPR_ASSERT(given <= UINT32_MAX - p->strgot);
     p->strgot += (uint32_t)given;
     p->state = parse_string;
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 }
 
 /* begin parsing a string - performs setup, calls parse_string */
-static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end, uint8_t binary,
-                              grpc_chttp2_hpack_parser_string *str) {
+static grpc_error *begin_parse_string(grpc_chttp2_hpack_parser *p,
+                                      const uint8_t *cur, const uint8_t *end,
+                                      uint8_t binary,
+                                      grpc_chttp2_hpack_parser_string *str) {
   p->strgot = 0;
   str->length = 0;
   p->parsing.str = str;
@@ -1330,58 +1408,50 @@
 }
 
 /* parse the key string */
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                            const uint8_t *end) {
+static grpc_error *parse_key_string(grpc_chttp2_hpack_parser *p,
+                                    const uint8_t *cur, const uint8_t *end) {
   return begin_parse_string(p, cur, end, NOT_BINARY, &p->key);
 }
 
 /* check if a key represents a binary header or not */
-typedef enum { BINARY_HEADER, PLAINTEXT_HEADER, ERROR_HEADER } is_binary_header;
 
-static is_binary_header is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
-  return grpc_is_binary_header(p->key.str, p->key.length) ? BINARY_HEADER
-                                                          : PLAINTEXT_HEADER;
+static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
+  return grpc_is_binary_header(p->key.str, p->key.length);
 }
 
-static is_binary_header is_binary_indexed_header(grpc_chttp2_hpack_parser *p) {
+static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
+                                            bool *is) {
   grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
   if (!elem) {
-    if (grpc_http_trace) {
-      gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
-    }
-    return ERROR_HEADER;
+    return grpc_error_set_int(
+        grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
+                           GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
+        GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
   }
-  return grpc_is_binary_header(
-             (const char *)GPR_SLICE_START_PTR(elem->key->slice),
-             GPR_SLICE_LENGTH(elem->key->slice))
-             ? BINARY_HEADER
-             : PLAINTEXT_HEADER;
+  *is =
+      grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(elem->key->slice),
+                            GPR_SLICE_LENGTH(elem->key->slice));
+  return GRPC_ERROR_NONE;
 }
 
 /* parse the value string */
-static int parse_value_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
-                              const uint8_t *end, is_binary_header type) {
-  switch (type) {
-    case BINARY_HEADER:
-      return begin_parse_string(p, cur, end, B64_BYTE0, &p->value);
-    case PLAINTEXT_HEADER:
-      return begin_parse_string(p, cur, end, NOT_BINARY, &p->value);
-    case ERROR_HEADER:
-      return 0;
-  }
-  /* Add code to prevent return without value error */
-  GPR_UNREACHABLE_CODE(return 0);
+static grpc_error *parse_value_string(grpc_chttp2_hpack_parser *p,
+                                      const uint8_t *cur, const uint8_t *end,
+                                      bool is_binary) {
+  return begin_parse_string(p, cur, end, is_binary ? B64_BYTE0 : NOT_BINARY,
+                            &p->value);
 }
 
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end) {
-  return parse_value_string(p, cur, end, is_binary_indexed_header(p));
+static grpc_error *parse_value_string_with_indexed_key(
+    grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) {
+  bool is_binary = false;
+  grpc_error *err = is_binary_indexed_header(p, &is_binary);
+  if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
+  return parse_value_string(p, cur, end, is_binary);
 }
 
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
-                                               const uint8_t *cur,
-                                               const uint8_t *end) {
+static grpc_error *parse_value_string_with_literal_key(
+    grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) {
   return parse_value_string(p, cur, end, is_binary_literal_header(p));
 }
 
@@ -1398,6 +1468,7 @@
   p->value.capacity = 0;
   p->value.length = 0;
   p->dynamic_table_update_allowed = 2;
+  p->last_error = GRPC_ERROR_NONE;
   grpc_chttp2_hptbl_init(&p->table);
 }
 
@@ -1408,12 +1479,14 @@
 
 void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p) {
   grpc_chttp2_hptbl_destroy(&p->table);
+  GRPC_ERROR_UNREF(p->last_error);
   gpr_free(p->key.str);
   gpr_free(p->value.str);
 }
 
-int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
-                                   const uint8_t *beg, const uint8_t *end) {
+grpc_error *grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
+                                           const uint8_t *beg,
+                                           const uint8_t *end) {
   /* TODO(ctiller): limit the distance of end from beg, and perform multiple
      steps in the event of a large chunk of data to limit
      stack space usage when no tail call optimization is
@@ -1421,7 +1494,7 @@
   return p->state(p, beg, end);
 }
 
-grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
+grpc_error *grpc_chttp2_header_parser_parse(
     grpc_exec_ctx *exec_ctx, void *hpack_parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@@ -1430,17 +1503,17 @@
   if (stream_parsing != NULL) {
     stream_parsing->stats.incoming.header_bytes += GPR_SLICE_LENGTH(slice);
   }
-  if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
-                                      GPR_SLICE_END_PTR(slice))) {
+  grpc_error *error = grpc_chttp2_hpack_parser_parse(
+      parser, GPR_SLICE_START_PTR(slice), GPR_SLICE_END_PTR(slice));
+  if (error != GRPC_ERROR_NONE) {
     GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    return error;
   }
   if (is_last) {
     if (parser->is_boundary && parser->state != parse_begin) {
-      gpr_log(GPR_ERROR,
-              "end of header frame not aligned with a hpack record boundary");
       GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-      return GRPC_CHTTP2_CONNECTION_ERROR;
+      return GRPC_ERROR_CREATE(
+          "end of header frame not aligned with a hpack record boundary");
     }
     /* need to check for null stream: this can occur if we receive an invalid
        stream id on a header */
@@ -1448,8 +1521,7 @@
       if (parser->is_boundary) {
         if (stream_parsing->header_frames_received ==
             GPR_ARRAY_SIZE(stream_parsing->got_metadata_on_parse)) {
-          gpr_log(GPR_ERROR, "too many trailer frames");
-          return GRPC_CHTTP2_CONNECTION_ERROR;
+          return GRPC_ERROR_CREATE("Too many trailer frames");
         }
         stream_parsing
             ->got_metadata_on_parse[stream_parsing->header_frames_received] = 1;
@@ -1468,5 +1540,5 @@
     parser->dynamic_table_update_allowed = 2;
   }
   GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h
index 855d6c5..78eb38d 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h
@@ -44,9 +44,8 @@
 
 typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
 
-typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p,
-                                              const uint8_t *beg,
-                                              const uint8_t *end);
+typedef grpc_error *(*grpc_chttp2_hpack_parser_state)(
+    grpc_chttp2_hpack_parser *p, const uint8_t *beg, const uint8_t *end);
 
 typedef struct {
   char *str;
@@ -59,6 +58,8 @@
   void (*on_header)(void *user_data, grpc_mdelem *md);
   void *on_header_user_data;
 
+  grpc_error *last_error;
+
   /* current parse state - or a function that implements it */
   grpc_chttp2_hpack_parser_state state;
   /* future states dependent on the opening op code */
@@ -103,12 +104,13 @@
 void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
 
 /* returns 1 on success, 0 on error */
-int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
-                                   const uint8_t *beg, const uint8_t *end);
+grpc_error *grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
+                                           const uint8_t *beg,
+                                           const uint8_t *end);
 
 /* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
    the transport */
-grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
+grpc_error *grpc_chttp2_header_parser_parse(
     grpc_exec_ctx *exec_ctx, void *hpack_parser,
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c
index 295f31c..2b73ec9 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.c
@@ -38,6 +38,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/lib/support/murmur_hash.h"
 
@@ -262,18 +263,19 @@
   tbl->max_bytes = max_bytes;
 }
 
-int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
-                                             uint32_t bytes) {
+grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                                     uint32_t bytes) {
   if (tbl->current_table_bytes == bytes) {
-    return 1;
+    return GRPC_ERROR_NONE;
   }
   if (bytes > tbl->max_bytes) {
-    if (grpc_http_trace) {
-      gpr_log(GPR_ERROR,
-              "Attempt to make hpack table %d bytes when max is %d bytes",
-              bytes, tbl->max_bytes);
-    }
-    return 0;
+    char *msg;
+    gpr_asprintf(&msg,
+                 "Attempt to make hpack table %d bytes when max is %d bytes",
+                 bytes, tbl->max_bytes);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
   if (grpc_http_trace) {
     gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
@@ -291,23 +293,25 @@
       rebuild_ents(tbl, new_cap);
     }
   }
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
   /* determine how many bytes of buffer this entry represents */
   size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
                       GPR_SLICE_LENGTH(md->value->slice) +
                       GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
 
   if (tbl->current_table_bytes > tbl->max_bytes) {
-    if (grpc_http_trace) {
-      gpr_log(GPR_ERROR,
-              "HPACK max table size reduced to %d but not reflected by hpack "
-              "stream (still at %d)",
-              tbl->max_bytes, tbl->current_table_bytes);
-    }
-    return 0;
+    char *msg;
+    gpr_asprintf(
+        &msg,
+        "HPACK max table size reduced to %d but not reflected by hpack "
+        "stream (still at %d)",
+        tbl->max_bytes, tbl->current_table_bytes);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
 
   /* we can't add elements bigger than the max table size */
@@ -324,7 +328,7 @@
     while (tbl->num_ents) {
       evict1(tbl);
     }
-    return 1;
+    return GRPC_ERROR_NONE;
   }
 
   /* evict entries to ensure no overflow */
@@ -339,7 +343,7 @@
   /* update accounting values */
   tbl->num_ents++;
   tbl->mem_used += (uint32_t)elem_bytes;
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h
index 074fea3..45bd925 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.h
@@ -36,6 +36,7 @@
 
 #include <grpc/support/port_platform.h>
 #include <grpc/support/slice.h>
+#include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/transport/metadata.h"
 
 /* HPACK header table */
@@ -87,15 +88,15 @@
 void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
 void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
                                      uint32_t max_bytes);
-int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
-                                             uint32_t bytes);
+grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                                     uint32_t bytes);
 
 /* lookup a table entry based on its hpack index */
 grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
                                       uint32_t index);
 /* add a table entry to the index */
-int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
-                          grpc_mdelem *md) GRPC_MUST_USE_RESULT;
+grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
+                                  grpc_mdelem *md) GRPC_MUST_USE_RESULT;
 /* Find a key/value pair in the table... returns the index in the table of the
    most similar entry, or 0 if the value was not found */
 typedef struct {
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index 7f3339a..54e72eb 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -156,7 +156,7 @@
   grpc_byte_stream base;
   gpr_refcount refs;
   struct grpc_chttp2_incoming_byte_stream *next_message;
-  int failed;
+  grpc_error *error;
 
   grpc_chttp2_transport *transport;
   grpc_chttp2_stream *stream;
@@ -275,10 +275,10 @@
   /* active parser */
   void *parser_data;
   grpc_chttp2_stream_parsing *incoming_stream;
-  grpc_chttp2_parse_error (*parser)(
-      grpc_exec_ctx *exec_ctx, void *parser_user_data,
-      grpc_chttp2_transport_parsing *transport_parsing,
-      grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
+  grpc_error *(*parser)(grpc_exec_ctx *exec_ctx, void *parser_user_data,
+                        grpc_chttp2_transport_parsing *transport_parsing,
+                        grpc_chttp2_stream_parsing *stream_parsing,
+                        gpr_slice slice, int is_last);
 
   /* received settings */
   uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS];
@@ -471,12 +471,12 @@
 } grpc_chttp2_stream_writing;
 
 struct grpc_chttp2_stream_parsing {
+  /** saw some stream level error */
+  grpc_error *forced_close_error;
   /** HTTP2 stream id for this stream, or zero if one has not been assigned */
   uint32_t id;
   /** has this stream received a close */
   uint8_t received_close;
-  /** saw a rst_stream */
-  uint8_t saw_rst_stream;
   /** how many header frames have we received? */
   uint8_t header_frames_received;
   /** which metadata did we get (on this parse) */
@@ -488,8 +488,6 @@
   int64_t incoming_window;
   /** parsing state for data frames */
   grpc_chttp2_data_parser data_parser;
-  /** reason give to rst_stream */
-  uint32_t rst_stream_reason;
   /** amount of window given */
   int64_t outgoing_window;
   /** number of bytes received - reset at end of parse thread execution */
@@ -532,7 +530,7 @@
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
     grpc_endpoint *endpoint);
 void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
-                                   void *transport_writing, bool success);
+                                   void *transport_writing, grpc_error *error);
 void grpc_chttp2_cleanup_writing(grpc_exec_ctx *exec_ctx,
                                  grpc_chttp2_transport_global *global,
                                  grpc_chttp2_transport_writing *writing);
@@ -541,9 +539,9 @@
                                  grpc_chttp2_transport_parsing *parsing);
 /** Process one slice of incoming data; return 1 if the connection is still
     viable after reading, or 0 if the connection should be torn down */
-int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice);
+grpc_error *grpc_chttp2_perform_read(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    gpr_slice slice);
 void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
                                grpc_chttp2_transport_global *global,
                                grpc_chttp2_transport_parsing *parsing);
@@ -673,9 +671,10 @@
 void grpc_chttp2_parsing_become_skip_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 
-void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
-                                       grpc_chttp2_stream_global *stream_global,
-                                       grpc_closure **pclosure, int success);
+void grpc_chttp2_complete_closure_step(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
+    grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
+    grpc_error *error);
 
 void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
                                       grpc_chttp2_transport *transport,
@@ -778,8 +777,8 @@
                              grpc_status_code status, gpr_slice *details);
 void grpc_chttp2_mark_stream_closed(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global, int close_reads,
-    int close_writes);
+    grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
+    grpc_error *error);
 void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
                                grpc_chttp2_transport_global *transport_global);
 
@@ -811,8 +810,8 @@
                                            grpc_chttp2_incoming_byte_stream *bs,
                                            gpr_slice slice);
 void grpc_chttp2_incoming_byte_stream_finished(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
-    int from_parsing_thread);
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
+    grpc_error *error, int from_parsing_thread);
 
 void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
                           grpc_chttp2_transport_parsing *parsing,
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 3c74258..7851340 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -49,30 +49,30 @@
   ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
                                                    parsing)))
 
-static int init_frame_parser(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing);
-static int init_header_frame_parser(
+static grpc_error *init_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static grpc_error *init_header_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     int is_continuation);
-static int init_data_frame_parser(
+static grpc_error *init_data_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_rst_stream_parser(
+static grpc_error *init_rst_stream_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_settings_frame_parser(
+static grpc_error *init_settings_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_window_update_frame_parser(
+static grpc_error *init_window_update_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
-static int init_ping_parser(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_parsing *transport_parsing);
-static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
-                              grpc_chttp2_transport_parsing *transport_parsing);
-static int init_skip_frame_parser(
+static grpc_error *init_ping_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static grpc_error *init_goaway_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
+static grpc_error *init_skip_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     int is_header);
 
-static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice, int is_last);
+static grpc_error *parse_frame_slice(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    gpr_slice slice, int is_last);
 
 void grpc_chttp2_prepare_to_read(
     grpc_chttp2_transport_global *transport_global,
@@ -230,38 +230,42 @@
       grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
     }
 
-    if (stream_parsing->saw_rst_stream) {
-      if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
-        grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
-            (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
-        char *status_details;
-        gpr_slice slice_details;
-        gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
-                     stream_parsing->rst_stream_reason);
-        slice_details = gpr_slice_from_copied_string(status_details);
-        gpr_free(status_details);
+    if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) {
+      intptr_t reason;
+      bool has_reason = grpc_error_get_int(stream_parsing->forced_close_error,
+                                           GRPC_ERROR_INT_HTTP2_ERROR, &reason);
+      if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) {
+        grpc_status_code status_code =
+            has_reason ? grpc_chttp2_http2_error_to_grpc_status(
+                             (grpc_chttp2_error_code)reason)
+                       : GRPC_STATUS_INTERNAL;
+        const char *status_details =
+            grpc_error_string(stream_parsing->forced_close_error);
+        gpr_slice slice_details = gpr_slice_from_copied_string(status_details);
+        grpc_error_free_string(status_details);
         grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
                                 status_code, &slice_details);
       }
       grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     1, 1);
+                                     1, 1, stream_parsing->forced_close_error);
     }
 
     if (stream_parsing->received_close) {
       grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     1, 0);
+                                     1, 0, GRPC_ERROR_NONE);
     }
   }
 }
 
-int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice) {
+grpc_error *grpc_chttp2_perform_read(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    gpr_slice slice) {
   uint8_t *beg = GPR_SLICE_START_PTR(slice);
   uint8_t *end = GPR_SLICE_END_PTR(slice);
   uint8_t *cur = beg;
+  grpc_error *err;
 
-  if (cur == end) return 1;
+  if (cur == end) return GRPC_ERROR_NONE;
 
   switch (transport_parsing->deframe_state) {
     case GRPC_DTS_CLIENT_PREFIX_0:
@@ -291,21 +295,25 @@
       while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
         if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                                                           ->deframe_state]) {
-          gpr_log(GPR_INFO,
-                  "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
-                  "at byte %d",
-                  GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
-                                                        ->deframe_state],
-                  (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
-                      [transport_parsing->deframe_state],
-                  *cur, (int)*cur, transport_parsing->deframe_state);
-          return 0;
+          char *msg;
+          gpr_asprintf(
+              &msg,
+              "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
+              "at byte %d",
+              GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
+                                                    ->deframe_state],
+              (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
+                  [transport_parsing->deframe_state],
+              *cur, (int)*cur, transport_parsing->deframe_state);
+          err = GRPC_ERROR_CREATE(msg);
+          gpr_free(msg);
+          return err;
         }
         ++cur;
         ++transport_parsing->deframe_state;
       }
       if (cur == end) {
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     dts_fh_0:
@@ -314,7 +322,7 @@
       transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_1;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_1:
@@ -322,7 +330,7 @@
       transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_2;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_2:
@@ -330,7 +338,7 @@
       transport_parsing->incoming_frame_size |= *cur;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_3;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_3:
@@ -338,7 +346,7 @@
       transport_parsing->incoming_frame_type = *cur;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_4;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_4:
@@ -346,7 +354,7 @@
       transport_parsing->incoming_frame_flags = *cur;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_5;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_5:
@@ -354,7 +362,7 @@
       transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_6;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_6:
@@ -362,7 +370,7 @@
       transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_7;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_7:
@@ -370,15 +378,16 @@
       transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
       if (++cur == end) {
         transport_parsing->deframe_state = GRPC_DTS_FH_8;
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FH_8:
       GPR_ASSERT(cur < end);
       transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
       transport_parsing->deframe_state = GRPC_DTS_FRAME;
-      if (!init_frame_parser(exec_ctx, transport_parsing)) {
-        return 0;
+      err = init_frame_parser(exec_ctx, transport_parsing);
+      if (err != GRPC_ERROR_NONE) {
+        return err;
       }
       if (transport_parsing->incoming_stream_id != 0 &&
           transport_parsing->incoming_stream_id >
@@ -387,62 +396,69 @@
             transport_parsing->incoming_stream_id;
       }
       if (transport_parsing->incoming_frame_size == 0) {
-        if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
-                               1)) {
-          return 0;
+        err = parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
+                                1);
+        if (err != GRPC_ERROR_NONE) {
+          return err;
         }
         transport_parsing->incoming_stream = NULL;
         if (++cur == end) {
           transport_parsing->deframe_state = GRPC_DTS_FH_0;
-          return 1;
+          return GRPC_ERROR_NONE;
         }
         goto dts_fh_0; /* loop */
       } else if (transport_parsing->incoming_frame_size >
                  transport_parsing->max_frame_size) {
-        gpr_log(GPR_DEBUG, "Frame size %d is larger than max frame size %d",
-                transport_parsing->incoming_frame_size,
-                transport_parsing->max_frame_size);
-        return 0;
+        char *msg;
+        gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
+                     transport_parsing->incoming_frame_size,
+                     transport_parsing->max_frame_size);
+        err = GRPC_ERROR_CREATE(msg);
+        gpr_free(msg);
+        return err;
       }
       if (++cur == end) {
-        return 1;
+        return GRPC_ERROR_NONE;
       }
     /* fallthrough */
     case GRPC_DTS_FRAME:
       GPR_ASSERT(cur < end);
       if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
-        if (!parse_frame_slice(exec_ctx, transport_parsing,
-                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
-                                                    (size_t)(end - beg)),
-                               1)) {
-          return 0;
+        err = parse_frame_slice(exec_ctx, transport_parsing,
+                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
+                                                     (size_t)(end - beg)),
+                                1);
+        if (err != GRPC_ERROR_NONE) {
+          return err;
         }
         transport_parsing->deframe_state = GRPC_DTS_FH_0;
         transport_parsing->incoming_stream = NULL;
-        return 1;
+        return GRPC_ERROR_NONE;
       } else if ((uint32_t)(end - cur) >
                  transport_parsing->incoming_frame_size) {
         size_t cur_offset = (size_t)(cur - beg);
-        if (!parse_frame_slice(
-                exec_ctx, transport_parsing,
-                gpr_slice_sub_no_ref(
-                    slice, cur_offset,
-                    cur_offset + transport_parsing->incoming_frame_size),
-                1)) {
-          return 0;
+        err = parse_frame_slice(
+            exec_ctx, transport_parsing,
+            gpr_slice_sub_no_ref(
+                slice, cur_offset,
+                cur_offset + transport_parsing->incoming_frame_size),
+            1);
+        if (err != GRPC_ERROR_NONE) {
+          return err;
         }
         cur += transport_parsing->incoming_frame_size;
         transport_parsing->incoming_stream = NULL;
         goto dts_fh_0; /* loop */
       } else {
-        if (!parse_frame_slice(exec_ctx, transport_parsing,
-                               gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
-                                                    (size_t)(end - beg)),
-                               0)) {
-          return 0;
+        err = parse_frame_slice(exec_ctx, transport_parsing,
+                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
+                                                     (size_t)(end - beg)),
+                                0);
+        if (err != GRPC_ERROR_NONE) {
+          return err;
         }
         transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       GPR_UNREACHABLE_CODE(return 0);
   }
@@ -450,23 +466,30 @@
   GPR_UNREACHABLE_CODE(return 0);
 }
 
-static int init_frame_parser(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing) {
+static grpc_error *init_frame_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
   if (transport_parsing->expect_continuation_stream_id != 0) {
     if (transport_parsing->incoming_frame_type !=
         GRPC_CHTTP2_FRAME_CONTINUATION) {
-      gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
-              transport_parsing->incoming_frame_type);
-      return 0;
+      char *msg;
+      gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x",
+                   transport_parsing->incoming_frame_type);
+      grpc_error *err = GRPC_ERROR_CREATE(msg);
+      gpr_free(msg);
+      return err;
     }
     if (transport_parsing->expect_continuation_stream_id !=
         transport_parsing->incoming_stream_id) {
-      gpr_log(GPR_ERROR,
-              "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
-              "grpc_chttp2_stream %08x",
-              transport_parsing->expect_continuation_stream_id,
-              transport_parsing->incoming_stream_id);
-      return 0;
+      char *msg;
+      gpr_asprintf(
+          &msg,
+          "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
+          "grpc_chttp2_stream %08x",
+          transport_parsing->expect_continuation_stream_id,
+          transport_parsing->incoming_stream_id);
+      grpc_error *err = GRPC_ERROR_CREATE(msg);
+      gpr_free(msg);
+      return err;
     }
     return init_header_frame_parser(exec_ctx, transport_parsing, 1);
   }
@@ -476,8 +499,7 @@
     case GRPC_CHTTP2_FRAME_HEADER:
       return init_header_frame_parser(exec_ctx, transport_parsing, 0);
     case GRPC_CHTTP2_FRAME_CONTINUATION:
-      gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
-      return 0;
+      return GRPC_ERROR_CREATE("Unexpected CONTINUATION frame");
     case GRPC_CHTTP2_FRAME_RST_STREAM:
       return init_rst_stream_parser(exec_ctx, transport_parsing);
     case GRPC_CHTTP2_FRAME_SETTINGS:
@@ -489,22 +511,24 @@
     case GRPC_CHTTP2_FRAME_GOAWAY:
       return init_goaway_parser(exec_ctx, transport_parsing);
     default:
-      gpr_log(GPR_ERROR, "Unknown frame type %02x",
-              transport_parsing->incoming_frame_type);
+      if (grpc_http_trace) {
+        gpr_log(GPR_ERROR, "Unknown frame type %02x",
+                transport_parsing->incoming_frame_type);
+      }
       return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
   }
 }
 
-static grpc_chttp2_parse_error skip_parser(
-    grpc_exec_ctx *exec_ctx, void *parser,
-    grpc_chttp2_transport_parsing *transport_parsing,
-    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
-  return GRPC_CHTTP2_PARSE_OK;
+static grpc_error *skip_parser(grpc_exec_ctx *exec_ctx, void *parser,
+                               grpc_chttp2_transport_parsing *transport_parsing,
+                               grpc_chttp2_stream_parsing *stream_parsing,
+                               gpr_slice slice, int is_last) {
+  return GRPC_ERROR_NONE;
 }
 
 static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
 
-static int init_skip_frame_parser(
+static grpc_error *init_skip_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     int is_header) {
   if (is_header) {
@@ -519,7 +543,7 @@
   } else {
     transport_parsing->parser = skip_parser;
   }
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 void grpc_chttp2_parsing_become_skip_parser(
@@ -529,22 +553,28 @@
       transport_parsing->parser == grpc_chttp2_header_parser_parse);
 }
 
-static grpc_chttp2_parse_error update_incoming_window(
+static grpc_error *update_incoming_window(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing) {
   uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
   if (incoming_frame_size > transport_parsing->incoming_window) {
-    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %" PRId64,
-            transport_parsing->incoming_frame_size,
-            transport_parsing->incoming_window);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
+                 transport_parsing->incoming_frame_size,
+                 transport_parsing->incoming_window);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
 
   if (incoming_frame_size > stream_parsing->incoming_window) {
-    gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %" PRId64,
-            transport_parsing->incoming_frame_size,
-            stream_parsing->incoming_window);
-    return GRPC_CHTTP2_CONNECTION_ERROR;
+    char *msg;
+    gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
+                 transport_parsing->incoming_frame_size,
+                 stream_parsing->incoming_window);
+    grpc_error *err = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
+    return err;
   }
 
   GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
@@ -555,15 +585,15 @@
 
   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
 
-  return GRPC_CHTTP2_PARSE_OK;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_data_frame_parser(
+static grpc_error *init_data_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
   grpc_chttp2_stream_parsing *stream_parsing =
       grpc_chttp2_parsing_lookup_stream(transport_parsing,
                                         transport_parsing->incoming_stream_id);
-  grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
+  grpc_error *err = GRPC_ERROR_NONE;
   if (stream_parsing == NULL) {
     return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
   }
@@ -571,33 +601,32 @@
   if (stream_parsing->received_close) {
     return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
   }
-  if (err == GRPC_CHTTP2_PARSE_OK) {
+  if (err == GRPC_ERROR_NONE) {
     err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
   }
-  if (err == GRPC_CHTTP2_PARSE_OK) {
+  if (err == GRPC_ERROR_NONE) {
     err = grpc_chttp2_data_parser_begin_frame(
-        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
+        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags,
+        stream_parsing->id);
   }
-  switch (err) {
-    case GRPC_CHTTP2_PARSE_OK:
-      transport_parsing->incoming_stream = stream_parsing;
-      transport_parsing->parser = grpc_chttp2_data_parser_parse;
-      transport_parsing->parser_data = &stream_parsing->data_parser;
-      return 1;
-    case GRPC_CHTTP2_STREAM_ERROR:
-      stream_parsing->received_close = 1;
-      stream_parsing->saw_rst_stream = 1;
-      stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
-      gpr_slice_buffer_add(
-          &transport_parsing->qbuf,
-          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
-                                        GRPC_CHTTP2_PROTOCOL_ERROR,
-                                        &stream_parsing->stats.outgoing));
-      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
-    case GRPC_CHTTP2_CONNECTION_ERROR:
-      return 0;
+  if (err == GRPC_ERROR_NONE) {
+    transport_parsing->incoming_stream = stream_parsing;
+    transport_parsing->parser = grpc_chttp2_data_parser_parse;
+    transport_parsing->parser_data = &stream_parsing->data_parser;
+    return GRPC_ERROR_NONE;
+  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
+    /* handle stream errors by closing the stream */
+    stream_parsing->received_close = 1;
+    stream_parsing->forced_close_error = err;
+    gpr_slice_buffer_add(
+        &transport_parsing->qbuf,
+        grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
+                                      GRPC_CHTTP2_PROTOCOL_ERROR,
+                                      &stream_parsing->stats.outgoing));
+    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
+  } else {
+    return err;
   }
-  GPR_UNREACHABLE_CODE(return 0);
 }
 
 static void free_timeout(void *p) { gpr_free(p); }
@@ -713,7 +742,7 @@
   GPR_TIMER_END("on_trailing_header", 0);
 }
 
-static int init_header_frame_parser(
+static grpc_error *init_header_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     int is_continuation) {
   uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
@@ -808,15 +837,16 @@
                            GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
     grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
   }
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_window_update_frame_parser(
+static grpc_error *init_window_update_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
-                                       &transport_parsing->simple.window_update,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
+  grpc_error *err = grpc_chttp2_window_update_parser_begin_frame(
+      &transport_parsing->simple.window_update,
+      transport_parsing->incoming_frame_size,
+      transport_parsing->incoming_frame_flags);
+  if (err != GRPC_ERROR_NONE) return err;
   if (transport_parsing->incoming_stream_id != 0) {
     grpc_chttp2_stream_parsing *stream_parsing =
         transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
@@ -828,26 +858,27 @@
   }
   transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
   transport_parsing->parser_data = &transport_parsing->simple.window_update;
-  return ok;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_ping_parser(grpc_exec_ctx *exec_ctx,
-                            grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
-                                       &transport_parsing->simple.ping,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
+static grpc_error *init_ping_parser(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
+  grpc_error *err = grpc_chttp2_ping_parser_begin_frame(
+      &transport_parsing->simple.ping, transport_parsing->incoming_frame_size,
+      transport_parsing->incoming_frame_flags);
+  if (err != GRPC_ERROR_NONE) return err;
   transport_parsing->parser = grpc_chttp2_ping_parser_parse;
   transport_parsing->parser_data = &transport_parsing->simple.ping;
-  return ok;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_rst_stream_parser(
+static grpc_error *init_rst_stream_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
-                                       &transport_parsing->simple.rst_stream,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
+  grpc_error *err = grpc_chttp2_rst_stream_parser_begin_frame(
+      &transport_parsing->simple.rst_stream,
+      transport_parsing->incoming_frame_size,
+      transport_parsing->incoming_frame_flags);
+  if (err != GRPC_ERROR_NONE) return err;
   grpc_chttp2_stream_parsing *stream_parsing =
       transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
           transport_parsing, transport_parsing->incoming_stream_id);
@@ -857,37 +888,32 @@
   stream_parsing->stats.incoming.framing_bytes += 9;
   transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
   transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
-  return ok;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_goaway_parser(
+static grpc_error *init_goaway_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
-                                       &transport_parsing->goaway_parser,
-                                       transport_parsing->incoming_frame_size,
-                                       transport_parsing->incoming_frame_flags);
+  grpc_error *err = grpc_chttp2_goaway_parser_begin_frame(
+      &transport_parsing->goaway_parser, transport_parsing->incoming_frame_size,
+      transport_parsing->incoming_frame_flags);
+  if (err != GRPC_ERROR_NONE) return err;
   transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
   transport_parsing->parser_data = &transport_parsing->goaway_parser;
-  return ok;
+  return GRPC_ERROR_NONE;
 }
 
-static int init_settings_frame_parser(
+static grpc_error *init_settings_frame_parser(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
-  int ok;
-
   if (transport_parsing->incoming_stream_id != 0) {
-    gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
-            transport_parsing->incoming_stream_id);
-    return 0;
+    return GRPC_ERROR_CREATE("Settings frame received for grpc_chttp2_stream");
   }
 
-  ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
-                                   &transport_parsing->simple.settings,
-                                   transport_parsing->incoming_frame_size,
-                                   transport_parsing->incoming_frame_flags,
-                                   transport_parsing->settings);
-  if (!ok) {
-    return 0;
+  grpc_error *err = grpc_chttp2_settings_parser_begin_frame(
+      &transport_parsing->simple.settings,
+      transport_parsing->incoming_frame_size,
+      transport_parsing->incoming_frame_flags, transport_parsing->settings);
+  if (err != GRPC_ERROR_NONE) {
+    return err;
   }
   if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
     transport_parsing->settings_ack_received = 1;
@@ -901,7 +927,7 @@
   }
   transport_parsing->parser = grpc_chttp2_settings_parser_parse;
   transport_parsing->parser_data = &transport_parsing->simple.settings;
-  return ok;
+  return GRPC_ERROR_NONE;
 }
 
 /*
@@ -910,34 +936,37 @@
 }
 */
 
-static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
-                             grpc_chttp2_transport_parsing *transport_parsing,
-                             gpr_slice slice, int is_last) {
+static grpc_error *parse_frame_slice(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
+    gpr_slice slice, int is_last) {
   grpc_chttp2_stream_parsing *stream_parsing =
       transport_parsing->incoming_stream;
-  switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
-                                    transport_parsing, stream_parsing, slice,
-                                    is_last)) {
-    case GRPC_CHTTP2_PARSE_OK:
-      if (stream_parsing) {
-        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
-                                                 stream_parsing);
-      }
-      return 1;
-    case GRPC_CHTTP2_STREAM_ERROR:
-      grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
-      if (stream_parsing) {
-        stream_parsing->saw_rst_stream = 1;
-        stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
-        gpr_slice_buffer_add(
-            &transport_parsing->qbuf,
-            grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
-                                          GRPC_CHTTP2_PROTOCOL_ERROR,
-                                          &stream_parsing->stats.outgoing));
-      }
-      return 1;
-    case GRPC_CHTTP2_CONNECTION_ERROR:
-      return 0;
+  grpc_error *err = transport_parsing->parser(
+      exec_ctx, transport_parsing->parser_data, transport_parsing,
+      stream_parsing, slice, is_last);
+  if (err == GRPC_ERROR_NONE) {
+    if (stream_parsing) {
+      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
+                                               stream_parsing);
+    }
+    return GRPC_ERROR_NONE;
+  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
+    if (grpc_http_trace) {
+      const char *msg = grpc_error_string(err);
+      gpr_log(GPR_ERROR, "%s", msg);
+      grpc_error_free_string(msg);
+    }
+    grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
+    if (stream_parsing) {
+      stream_parsing->forced_close_error = err;
+      gpr_slice_buffer_add(
+          &transport_parsing->qbuf,
+          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
+                                        GRPC_CHTTP2_PROTOCOL_ERROR,
+                                        &stream_parsing->stats.outgoing));
+    } else {
+      GRPC_ERROR_UNREF(err);
+    }
   }
-  GPR_UNREACHABLE_CODE(return 0);
+  return err;
 }
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index a8fb463..add7678 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -187,7 +187,8 @@
     grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf,
                         &transport_writing->done_cb);
   } else {
-    grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &transport_writing->done_cb, GRPC_ERROR_NONE,
+                        NULL);
   }
 }
 
@@ -334,25 +335,27 @@
       transport_global, transport_writing, &stream_global, &stream_writing)) {
     if (stream_writing->sent_initial_metadata) {
       grpc_chttp2_complete_closure_step(
-          exec_ctx, stream_global,
-          &stream_global->send_initial_metadata_finished, 1);
+          exec_ctx, transport_global, stream_global,
+          &stream_global->send_initial_metadata_finished, GRPC_ERROR_NONE);
     }
     grpc_transport_move_one_way_stats(&stream_writing->stats,
                                       &stream_global->stats.outgoing);
     if (stream_writing->sent_message) {
       GPR_ASSERT(stream_writing->send_message == NULL);
       grpc_chttp2_complete_closure_step(
-          exec_ctx, stream_global, &stream_global->send_message_finished, 1);
+          exec_ctx, transport_global, stream_global,
+          &stream_global->send_message_finished, GRPC_ERROR_NONE);
       stream_writing->sent_message = 0;
     }
     if (stream_writing->sent_trailing_metadata) {
       grpc_chttp2_complete_closure_step(
-          exec_ctx, stream_global,
-          &stream_global->send_trailing_metadata_finished, 1);
+          exec_ctx, transport_global, stream_global,
+          &stream_global->send_trailing_metadata_finished, GRPC_ERROR_NONE);
     }
     if (stream_writing->sent_trailing_metadata) {
       grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
-                                     !transport_global->is_client, 1);
+                                     !transport_global->is_client, 1,
+                                     GRPC_ERROR_NONE);
     }
     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
   }
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 1bb53b7..25d8aca 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -159,11 +159,11 @@
 static void enqueue_callbacks(grpc_closure *callback_list[]) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   if (callback_list[0]) {
-    grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL);
+    grpc_exec_ctx_sched(&exec_ctx, callback_list[0], GRPC_ERROR_NONE, NULL);
     callback_list[0] = NULL;
   }
   if (callback_list[1]) {
-    grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL);
+    grpc_exec_ctx_sched(&exec_ctx, callback_list[1], GRPC_ERROR_NONE, NULL);
     callback_list[1] = NULL;
   }
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c
index d53ce90..79ceeb6 100644
--- a/src/core/lib/channel/channel_args.c
+++ b/src/core/lib/channel/channel_args.c
@@ -149,6 +149,7 @@
 
 void grpc_channel_args_destroy(grpc_channel_args *a) {
   size_t i;
+  if (!a) return;
   for (i = 0; i < a->num_args; i++) {
     switch (a->args[i].type) {
       case GRPC_ARG_STRING:
@@ -212,7 +213,7 @@
 
 grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
     grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) {
-  int *states_arg;
+  int *states_arg = NULL;
   grpc_channel_args *result = *a;
   const int states_arg_found =
       find_compression_algorithm_states_bitset(*a, &states_arg);
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index 32f4f8d..32ebe53 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -154,11 +154,11 @@
 static void continue_send_message(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem);
 
-static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
+static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
   grpc_call_element *elem = elemp;
   call_data *calld = elem->call_data;
   gpr_slice_buffer_reset_and_unref(&calld->slices);
-  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, success);
+  calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
 }
 
 static void finish_send_message(grpc_exec_ctx *exec_ctx,
@@ -206,7 +206,7 @@
   grpc_call_next_op(exec_ctx, elem, &calld->send_op);
 }
 
-static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
+static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
   grpc_call_element *elem = elemp;
   call_data *calld = elem->call_data;
   gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 792f0d8..ab6c6c9 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -101,7 +101,8 @@
   return md;
 }
 
-static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
+                       grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
   client_recv_filter_args a;
@@ -109,7 +110,7 @@
   a.exec_ctx = exec_ctx;
   grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter,
                              &a);
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
 }
 
 static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index 922f771..d0beebd 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -142,10 +142,11 @@
   }
 }
 
-static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
+                       grpc_error *err) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
-  if (success) {
+  if (err == GRPC_ERROR_NONE) {
     server_filter_args a;
     a.elem = elem;
     a.exec_ctx = exec_ctx;
@@ -157,27 +158,35 @@
         calld->seen_path && calld->seen_authority) {
       /* do nothing */
     } else {
+      err = GRPC_ERROR_CREATE("Bad incoming HTTP headers");
       if (!calld->seen_path) {
-        gpr_log(GPR_ERROR, "Missing :path header");
+        err = grpc_error_add_child(err,
+                                   GRPC_ERROR_CREATE("Missing :path header"));
       }
       if (!calld->seen_authority) {
-        gpr_log(GPR_ERROR, "Missing :authority header");
+        err = grpc_error_add_child(
+            err, GRPC_ERROR_CREATE("Missing :authority header"));
       }
       if (!calld->seen_method) {
-        gpr_log(GPR_ERROR, "Missing :method header");
+        err = grpc_error_add_child(err,
+                                   GRPC_ERROR_CREATE("Missing :method header"));
       }
       if (!calld->seen_scheme) {
-        gpr_log(GPR_ERROR, "Missing :scheme header");
+        err = grpc_error_add_child(err,
+                                   GRPC_ERROR_CREATE("Missing :scheme header"));
       }
       if (!calld->seen_te_trailers) {
-        gpr_log(GPR_ERROR, "Missing te trailers header");
+        err = grpc_error_add_child(
+            err, GRPC_ERROR_CREATE("Missing te: trailers header"));
       }
       /* Error this call out */
-      success = 0;
       grpc_call_element_send_cancel(exec_ctx, elem);
     }
+  } else {
+    GRPC_ERROR_REF(err);
   }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, err);
+  GRPC_ERROR_UNREF(err);
 }
 
 static void hs_mutate_op(grpc_call_element *elem,
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index e8957bf..18135bc 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -39,12 +39,14 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
 
 #include "src/core/lib/http/format_request.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/support/string.h"
 
@@ -59,8 +61,7 @@
   gpr_timespec deadline;
   int have_read_byte;
   const grpc_httpcli_handshaker *handshaker;
-  grpc_httpcli_response_cb on_response;
-  void *user_data;
+  grpc_closure *on_done;
   grpc_httpcli_context *context;
   grpc_polling_entity *pollent;
   grpc_iomgr_object iomgr_obj;
@@ -69,6 +70,7 @@
   grpc_closure on_read;
   grpc_closure done_write;
   grpc_closure connected;
+  grpc_error *overall_error;
 } internal_request;
 
 static grpc_httpcli_get_override g_get_override = NULL;
@@ -76,6 +78,7 @@
 
 static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
                                 grpc_endpoint *endpoint, const char *host,
+                                gpr_timespec deadline,
                                 void (*on_done)(grpc_exec_ctx *exec_ctx,
                                                 void *arg,
                                                 grpc_endpoint *endpoint)) {
@@ -93,14 +96,14 @@
   grpc_pollset_set_destroy(context->pollset_set);
 }
 
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
+                         grpc_error *due_to_error);
 
 static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
-                   int success) {
+                   grpc_error *error) {
   grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent,
                                            req->context->pollset_set);
-  req->on_response(exec_ctx, req->user_data,
-                   success ? &req->parser.http.response : NULL);
+  grpc_exec_ctx_sched(exec_ctx, req->on_done, error, NULL);
   grpc_http_parser_destroy(&req->parser);
   if (req->addresses != NULL) {
     grpc_resolved_addresses_destroy(req->addresses);
@@ -114,39 +117,49 @@
   grpc_iomgr_unregister_object(&req->iomgr_obj);
   gpr_slice_buffer_destroy(&req->incoming);
   gpr_slice_buffer_destroy(&req->outgoing);
+  GRPC_ERROR_UNREF(req->overall_error);
   gpr_free(req);
 }
 
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success);
+static void append_error(internal_request *req, grpc_error *error) {
+  if (req->overall_error == GRPC_ERROR_NONE) {
+    req->overall_error = GRPC_ERROR_CREATE("Failed HTTP/1 client request");
+  }
+  grpc_resolved_address *addr = &req->addresses->addrs[req->next_address - 1];
+  char *addr_text = grpc_sockaddr_to_uri((struct sockaddr *)addr->addr);
+  req->overall_error = grpc_error_add_child(
+      req->overall_error,
+      grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_text));
+  gpr_free(addr_text);
+}
 
 static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
   grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
 }
 
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
+                    grpc_error *error) {
   internal_request *req = user_data;
   size_t i;
 
   for (i = 0; i < req->incoming.count; i++) {
     if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
       req->have_read_byte = 1;
-      if (!grpc_http_parser_parse(&req->parser, req->incoming.slices[i])) {
-        finish(exec_ctx, req, 0);
+      grpc_error *err =
+          grpc_http_parser_parse(&req->parser, req->incoming.slices[i]);
+      if (err != GRPC_ERROR_NONE) {
+        finish(exec_ctx, req, err);
         return;
       }
     }
   }
 
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     do_read(exec_ctx, req);
   } else if (!req->have_read_byte) {
-    next_address(exec_ctx, req);
+    next_address(exec_ctx, req, GRPC_ERROR_REF(error));
   } else {
-    int parse_success = grpc_http_parser_eof(&req->parser);
-    if (parse_success && (req->parser.type != GRPC_HTTP_RESPONSE)) {
-      parse_success = 0;
-    }
-    finish(exec_ctx, req, parse_success);
+    finish(exec_ctx, req, grpc_http_parser_eof(&req->parser));
   }
 }
 
@@ -154,12 +167,12 @@
   do_read(exec_ctx, req);
 }
 
-static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   internal_request *req = arg;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     on_written(exec_ctx, req);
   } else {
-    next_address(exec_ctx, req);
+    next_address(exec_ctx, req, GRPC_ERROR_REF(error));
   }
 }
 
@@ -174,7 +187,8 @@
   internal_request *req = arg;
 
   if (!ep) {
-    next_address(exec_ctx, req);
+    next_address(exec_ctx, req,
+                 GRPC_ERROR_CREATE("Unexplained handshake failure"));
     return;
   }
 
@@ -182,23 +196,30 @@
   start_write(exec_ctx, req);
 }
 
-static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void on_connected(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
   internal_request *req = arg;
 
   if (!req->ep) {
-    next_address(exec_ctx, req);
+    next_address(exec_ctx, req, GRPC_ERROR_REF(error));
     return;
   }
   req->handshaker->handshake(
       exec_ctx, req, req->ep,
       req->ssl_host_override ? req->ssl_host_override : req->host,
-      on_handshake_done);
+      req->deadline, on_handshake_done);
 }
 
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
+                         grpc_error *error) {
   grpc_resolved_address *addr;
+  if (error != GRPC_ERROR_NONE) {
+    append_error(req, error);
+  }
   if (req->next_address == req->addresses->naddrs) {
-    finish(exec_ctx, req, 0);
+    finish(exec_ctx, req,
+           GRPC_ERROR_CREATE_REFERENCING("Failed HTTP requests to all targets",
+                                         &req->overall_error, 1));
     return;
   }
   addr = &req->addresses->addrs[req->next_address++];
@@ -208,34 +229,34 @@
       (struct sockaddr *)&addr->addr, addr->len, req->deadline);
 }
 
-static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                        grpc_resolved_addresses *addresses) {
+static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   internal_request *req = arg;
-  if (!addresses) {
-    finish(exec_ctx, req, 0);
+  if (error != GRPC_ERROR_NONE) {
+    finish(exec_ctx, req, error);
     return;
   }
-  req->addresses = addresses;
   req->next_address = 0;
-  next_address(exec_ctx, req);
+  next_address(exec_ctx, req, GRPC_ERROR_NONE);
 }
 
-static void internal_request_begin(
-    grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
-    grpc_polling_entity *pollent, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data, const char *name, gpr_slice request_text) {
+static void internal_request_begin(grpc_exec_ctx *exec_ctx,
+                                   grpc_httpcli_context *context,
+                                   grpc_polling_entity *pollent,
+                                   const grpc_httpcli_request *request,
+                                   gpr_timespec deadline, grpc_closure *on_done,
+                                   grpc_httpcli_response *response,
+                                   const char *name, gpr_slice request_text) {
   internal_request *req = gpr_malloc(sizeof(internal_request));
   memset(req, 0, sizeof(*req));
   req->request_text = request_text;
-  grpc_http_parser_init(&req->parser);
-  req->on_response = on_response;
-  req->user_data = user_data;
+  grpc_http_parser_init(&req->parser, GRPC_HTTP_RESPONSE, response);
+  req->on_done = on_done;
   req->deadline = deadline;
   req->handshaker =
       request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
   req->context = context;
   req->pollent = pollent;
+  req->overall_error = GRPC_ERROR_NONE;
   grpc_closure_init(&req->on_read, on_read, req);
   grpc_closure_init(&req->done_write, done_write, req);
   gpr_slice_buffer_init(&req->incoming);
@@ -248,22 +269,22 @@
   grpc_polling_entity_add_to_pollset_set(exec_ctx, req->pollent,
                                          req->context->pollset_set);
   grpc_resolve_address(exec_ctx, request->host, req->handshaker->default_port,
-                       on_resolved, req);
+                       grpc_closure_create(on_resolved, req), &req->addresses);
 }
 
 void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
                       grpc_polling_entity *pollent,
                       const grpc_httpcli_request *request,
-                      gpr_timespec deadline,
-                      grpc_httpcli_response_cb on_response, void *user_data) {
+                      gpr_timespec deadline, grpc_closure *on_done,
+                      grpc_httpcli_response *response) {
   char *name;
   if (g_get_override &&
-      g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
+      g_get_override(exec_ctx, request, deadline, on_done, response)) {
     return;
   }
   gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->http.path);
-  internal_request_begin(exec_ctx, context, pollent, request, deadline,
-                         on_response, user_data, name,
+  internal_request_begin(exec_ctx, context, pollent, request, deadline, on_done,
+                         response, name,
                          grpc_httpcli_format_get_request(request));
   gpr_free(name);
 }
@@ -272,18 +293,18 @@
                        grpc_polling_entity *pollent,
                        const grpc_httpcli_request *request,
                        const char *body_bytes, size_t body_size,
-                       gpr_timespec deadline,
-                       grpc_httpcli_response_cb on_response, void *user_data) {
+                       gpr_timespec deadline, grpc_closure *on_done,
+                       grpc_httpcli_response *response) {
   char *name;
   if (g_post_override &&
       g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
-                      on_response, user_data)) {
+                      on_done, response)) {
     return;
   }
   gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->http.path);
   internal_request_begin(
-      exec_ctx, context, pollent, request, deadline, on_response, user_data,
-      name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
+      exec_ctx, context, pollent, request, deadline, on_done, response, name,
+      grpc_httpcli_format_post_request(request, body_bytes, body_size));
   gpr_free(name);
 }
 
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
index 7e7784f..662e176 100644
--- a/src/core/lib/http/httpcli.h
+++ b/src/core/lib/http/httpcli.h
@@ -57,7 +57,7 @@
 typedef struct {
   const char *default_port;
   void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint,
-                    const char *host,
+                    const char *host, gpr_timespec deadline,
                     void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
                                     grpc_endpoint *endpoint));
 } grpc_httpcli_handshaker;
@@ -82,11 +82,6 @@
 /* Expose the parser response type as a httpcli response too */
 typedef struct grpc_http_response grpc_httpcli_response;
 
-/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
-typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
-                                         void *user_data,
-                                         const grpc_http_response *response);
-
 void grpc_httpcli_context_init(grpc_httpcli_context *context);
 void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
 
@@ -103,8 +98,8 @@
 void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
                       grpc_polling_entity *pollent,
                       const grpc_httpcli_request *request,
-                      gpr_timespec deadline,
-                      grpc_httpcli_response_cb on_response, void *user_data);
+                      gpr_timespec deadline, grpc_closure *on_complete,
+                      grpc_httpcli_response *response);
 
 /* Asynchronously perform a HTTP POST.
    'context' specifies the http context under which to do the post
@@ -125,19 +120,19 @@
                        grpc_polling_entity *pollent,
                        const grpc_httpcli_request *request,
                        const char *body_bytes, size_t body_size,
-                       gpr_timespec deadline,
-                       grpc_httpcli_response_cb on_response, void *user_data);
+                       gpr_timespec deadline, grpc_closure *on_complete,
+                       grpc_httpcli_response *response);
 
 /* override functions return 1 if they handled the request, 0 otherwise */
 typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
                                          const grpc_httpcli_request *request,
                                          gpr_timespec deadline,
-                                         grpc_httpcli_response_cb on_response,
-                                         void *user_data);
+                                         grpc_closure *on_complete,
+                                         grpc_httpcli_response *response);
 typedef int (*grpc_httpcli_post_override)(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
     const char *body_bytes, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data);
+    grpc_closure *on_complete, grpc_httpcli_response *response);
 
 void grpc_httpcli_set_override(grpc_httpcli_get_override get,
                                grpc_httpcli_post_override post);
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index 5590928..a57d93b 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -61,6 +61,7 @@
 static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
                                      grpc_channel_security_connector *sc,
                                      grpc_endpoint *nonsecure_endpoint,
+                                     gpr_timespec deadline,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
   grpc_httpcli_ssl_channel_security_connector *c =
@@ -79,7 +80,7 @@
     cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
-                               nonsecure_endpoint, cb, user_data);
+                               nonsecure_endpoint, deadline, cb, user_data);
   }
 }
 
@@ -163,6 +164,7 @@
 
 static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
                           grpc_endpoint *tcp, const char *host,
+                          gpr_timespec deadline,
                           void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
                                           grpc_endpoint *endpoint)) {
   grpc_channel_security_connector *sc = NULL;
@@ -181,7 +183,7 @@
                  pem_root_certs, pem_root_certs_size, host, &sc) ==
              GRPC_SECURITY_OK);
   grpc_channel_security_connector_do_handshake(
-      exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
+      exec_ctx, sc, tcp, deadline, on_secure_transport_setup_done, c);
   GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
 }
 
diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c
index 09b2ed4..92ed08a 100644
--- a/src/core/lib/http/parser.c
+++ b/src/core/lib/http/parser.c
@@ -48,37 +48,38 @@
   return out;
 }
 
-static int handle_response_line(grpc_http_parser *parser) {
+static grpc_error *handle_response_line(grpc_http_parser *parser) {
   uint8_t *beg = parser->cur_line;
   uint8_t *cur = beg;
   uint8_t *end = beg + parser->cur_line_length;
 
-  if (cur == end || *cur++ != 'H') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'P') goto error;
-  if (cur == end || *cur++ != '/') goto error;
-  if (cur == end || *cur++ != '1') goto error;
-  if (cur == end || *cur++ != '.') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '1') goto error;
-  if (cur == end || *cur++ != ' ') goto error;
-  if (cur == end || *cur < '1' || *cur++ > '9') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
-  if (cur == end || *cur < '0' || *cur++ > '9') goto error;
-  parser->http.response.status =
+  if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
+  if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
+  if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'");
+  if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'");
+  if (cur == end || *cur < '0' || *cur++ > '1') {
+    return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1");
+  }
+  if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
+  if (cur == end || *cur < '1' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  if (cur == end || *cur < '0' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  if (cur == end || *cur < '0' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  parser->http.response->status =
       (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
-  if (cur == end || *cur++ != ' ') goto error;
+  if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
 
   /* we don't really care about the status code message */
 
-  return 1;
-
-error:
-  if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
-  return 0;
+  return GRPC_ERROR_NONE;
 }
 
-static int handle_request_line(grpc_http_parser *parser) {
+static grpc_error *handle_request_line(grpc_http_parser *parser) {
   uint8_t *beg = parser->cur_line;
   uint8_t *cur = beg;
   uint8_t *end = beg + parser->cur_line_length;
@@ -87,84 +88,81 @@
 
   while (cur != end && *cur++ != ' ')
     ;
-  if (cur == end) goto error;
-  parser->http.request.method = buf2str(beg, (size_t)(cur - beg - 1));
+  if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line");
+  parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1));
 
   beg = cur;
   while (cur != end && *cur++ != ' ')
     ;
-  if (cur == end) goto error;
-  parser->http.request.path = buf2str(beg, (size_t)(cur - beg - 1));
+  if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line");
+  parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1));
 
-  if (cur == end || *cur++ != 'H') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'T') goto error;
-  if (cur == end || *cur++ != 'P') goto error;
-  if (cur == end || *cur++ != '/') goto error;
+  if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
+  if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
   vers_major = (uint8_t)(*cur++ - '1' + 1);
   ++cur;
-  if (cur == end) goto error;
+  if (cur == end)
+    return GRPC_ERROR_CREATE("End of line in HTTP version string");
   vers_minor = (uint8_t)(*cur++ - '1' + 1);
 
   if (vers_major == 1) {
     if (vers_minor == 0) {
-      parser->http.request.version = GRPC_HTTP_HTTP10;
+      parser->http.request->version = GRPC_HTTP_HTTP10;
     } else if (vers_minor == 1) {
-      parser->http.request.version = GRPC_HTTP_HTTP11;
+      parser->http.request->version = GRPC_HTTP_HTTP11;
     } else {
-      goto error;
+      return GRPC_ERROR_CREATE(
+          "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
     }
   } else if (vers_major == 2) {
     if (vers_minor == 0) {
-      parser->http.request.version = GRPC_HTTP_HTTP20;
+      parser->http.request->version = GRPC_HTTP_HTTP20;
     } else {
-      goto error;
+      return GRPC_ERROR_CREATE(
+          "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
     }
   } else {
-    goto error;
+    return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
   }
 
-  return 1;
-
-error:
-  if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
-  return 0;
+  return GRPC_ERROR_NONE;
 }
 
-static int handle_first_line(grpc_http_parser *parser) {
-  if (parser->cur_line[0] == 'H') {
-    parser->type = GRPC_HTTP_RESPONSE;
-    return handle_response_line(parser);
-  } else {
-    parser->type = GRPC_HTTP_REQUEST;
-    return handle_request_line(parser);
+static grpc_error *handle_first_line(grpc_http_parser *parser) {
+  switch (parser->type) {
+    case GRPC_HTTP_REQUEST:
+      return handle_request_line(parser);
+    case GRPC_HTTP_RESPONSE:
+      return handle_response_line(parser);
   }
+  GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
 }
 
-static int add_header(grpc_http_parser *parser) {
+static grpc_error *add_header(grpc_http_parser *parser) {
   uint8_t *beg = parser->cur_line;
   uint8_t *cur = beg;
   uint8_t *end = beg + parser->cur_line_length;
   size_t *hdr_count = NULL;
   grpc_http_header **hdrs = NULL;
   grpc_http_header hdr = {NULL, NULL};
+  grpc_error *error = GRPC_ERROR_NONE;
 
   GPR_ASSERT(cur != end);
 
   if (*cur == ' ' || *cur == '\t') {
-    if (grpc_http1_trace)
-      gpr_log(GPR_ERROR, "Continued header lines not supported yet");
-    goto error;
+    error = GRPC_ERROR_CREATE("Continued header lines not supported yet");
+    goto done;
   }
 
   while (cur != end && *cur != ':') {
     cur++;
   }
   if (cur == end) {
-    if (grpc_http1_trace) {
-      gpr_log(GPR_ERROR, "Didn't find ':' in header string");
-    }
-    goto error;
+    error = GRPC_ERROR_CREATE("Didn't find ':' in header string");
+    goto done;
   }
   GPR_ASSERT(cur >= beg);
   hdr.key = buf2str(beg, (size_t)(cur - beg));
@@ -176,14 +174,15 @@
   GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
   hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
 
-  if (parser->type == GRPC_HTTP_RESPONSE) {
-    hdr_count = &parser->http.response.hdr_count;
-    hdrs = &parser->http.response.hdrs;
-  } else if (parser->type == GRPC_HTTP_REQUEST) {
-    hdr_count = &parser->http.request.hdr_count;
-    hdrs = &parser->http.request.hdrs;
-  } else {
-    return 0;
+  switch (parser->type) {
+    case GRPC_HTTP_RESPONSE:
+      hdr_count = &parser->http.response->hdr_count;
+      hdrs = &parser->http.response->hdrs;
+      break;
+    case GRPC_HTTP_REQUEST:
+      hdr_count = &parser->http.request->hdr_count;
+      hdrs = &parser->http.request->hdrs;
+      break;
   }
 
   if (*hdr_count == parser->hdr_capacity) {
@@ -192,20 +191,21 @@
     *hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
   }
   (*hdrs)[(*hdr_count)++] = hdr;
-  return 1;
 
-error:
-  gpr_free(hdr.key);
-  gpr_free(hdr.value);
-  return 0;
+done:
+  if (error != GRPC_ERROR_NONE) {
+    gpr_free(hdr.key);
+    gpr_free(hdr.value);
+  }
+  return error;
 }
 
-static int finish_line(grpc_http_parser *parser) {
+static grpc_error *finish_line(grpc_http_parser *parser) {
+  grpc_error *err;
   switch (parser->state) {
     case GRPC_HTTP_FIRST_LINE:
-      if (!handle_first_line(parser)) {
-        return 0;
-      }
+      err = handle_first_line(parser);
+      if (err != GRPC_ERROR_NONE) return err;
       parser->state = GRPC_HTTP_HEADERS;
       break;
     case GRPC_HTTP_HEADERS:
@@ -213,30 +213,31 @@
         parser->state = GRPC_HTTP_BODY;
         break;
       }
-      if (!add_header(parser)) {
-        return 0;
+      err = add_header(parser);
+      if (err != GRPC_ERROR_NONE) {
+        return err;
       }
       break;
     case GRPC_HTTP_BODY:
-      GPR_UNREACHABLE_CODE(return 0);
+      GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
   }
 
   parser->cur_line_length = 0;
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
+static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) {
   size_t *body_length = NULL;
   char **body = NULL;
 
   if (parser->type == GRPC_HTTP_RESPONSE) {
-    body_length = &parser->http.response.body_length;
-    body = &parser->http.response.body;
+    body_length = &parser->http.response->body_length;
+    body = &parser->http.response->body;
   } else if (parser->type == GRPC_HTTP_REQUEST) {
-    body_length = &parser->http.request.body_length;
-    body = &parser->http.request.body;
+    body_length = &parser->http.request->body_length;
+    body = &parser->http.request->body;
   } else {
-    return 0;
+    GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
   }
 
   if (*body_length == parser->body_capacity) {
@@ -246,34 +247,34 @@
   (*body)[*body_length] = (char)byte;
   (*body_length)++;
 
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-static int check_line(grpc_http_parser *parser) {
+static bool check_line(grpc_http_parser *parser) {
   if (parser->cur_line_length >= 2 &&
       parser->cur_line[parser->cur_line_length - 2] == '\r' &&
       parser->cur_line[parser->cur_line_length - 1] == '\n') {
-    return 1;
+    return true;
   }
 
   // HTTP request with \n\r line termiantors.
   else if (parser->cur_line_length >= 2 &&
            parser->cur_line[parser->cur_line_length - 2] == '\n' &&
            parser->cur_line[parser->cur_line_length - 1] == '\r') {
-    return 1;
+    return true;
   }
 
   // HTTP request with only \n line terminators.
   else if (parser->cur_line_length >= 1 &&
            parser->cur_line[parser->cur_line_length - 1] == '\n') {
     parser->cur_line_end_length = 1;
-    return 1;
+    return true;
   }
 
-  return 0;
+  return false;
 }
 
-static int addbyte(grpc_http_parser *parser, uint8_t byte) {
+static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) {
   switch (parser->state) {
     case GRPC_HTTP_FIRST_LINE:
     case GRPC_HTTP_HEADERS:
@@ -288,7 +289,7 @@
       if (check_line(parser)) {
         return finish_line(parser);
       } else {
-        return 1;
+        return GRPC_ERROR_NONE;
       }
       GPR_UNREACHABLE_CODE(return 0);
     case GRPC_HTTP_BODY:
@@ -297,46 +298,53 @@
   GPR_UNREACHABLE_CODE(return 0);
 }
 
-void grpc_http_parser_init(grpc_http_parser *parser) {
+void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
+                           void *request_or_response) {
   memset(parser, 0, sizeof(*parser));
   parser->state = GRPC_HTTP_FIRST_LINE;
-  parser->type = GRPC_HTTP_UNKNOWN;
+  parser->type = type;
+  parser->http.request_or_response = request_or_response;
   parser->cur_line_end_length = 2;
 }
 
-void grpc_http_parser_destroy(grpc_http_parser *parser) {
+void grpc_http_parser_destroy(grpc_http_parser *parser) {}
+
+void grpc_http_request_destroy(grpc_http_request *request) {
   size_t i;
-  if (parser->type == GRPC_HTTP_RESPONSE) {
-    gpr_free(parser->http.response.body);
-    for (i = 0; i < parser->http.response.hdr_count; i++) {
-      gpr_free(parser->http.response.hdrs[i].key);
-      gpr_free(parser->http.response.hdrs[i].value);
-    }
-    gpr_free(parser->http.response.hdrs);
-  } else if (parser->type == GRPC_HTTP_REQUEST) {
-    gpr_free(parser->http.request.body);
-    for (i = 0; i < parser->http.request.hdr_count; i++) {
-      gpr_free(parser->http.request.hdrs[i].key);
-      gpr_free(parser->http.request.hdrs[i].value);
-    }
-    gpr_free(parser->http.request.hdrs);
-    gpr_free(parser->http.request.method);
-    gpr_free(parser->http.request.path);
+  gpr_free(request->body);
+  for (i = 0; i < request->hdr_count; i++) {
+    gpr_free(request->hdrs[i].key);
+    gpr_free(request->hdrs[i].value);
   }
+  gpr_free(request->hdrs);
+  gpr_free(request->method);
+  gpr_free(request->path);
 }
 
-int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
+void grpc_http_response_destroy(grpc_http_response *response) {
+  size_t i;
+  gpr_free(response->body);
+  for (i = 0; i < response->hdr_count; i++) {
+    gpr_free(response->hdrs[i].key);
+    gpr_free(response->hdrs[i].value);
+  }
+  gpr_free(response->hdrs);
+}
+
+grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
   size_t i;
 
   for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
-    if (!addbyte(parser, GPR_SLICE_START_PTR(slice)[i])) {
-      return 0;
-    }
+    grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]);
+    if (err != GRPC_ERROR_NONE) return err;
   }
 
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_http_parser_eof(grpc_http_parser *parser) {
-  return parser->state == GRPC_HTTP_BODY;
+grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) {
+  if (parser->state != GRPC_HTTP_BODY) {
+    return GRPC_ERROR_CREATE("Did not finish headers");
+  }
+  return GRPC_ERROR_NONE;
 }
diff --git a/src/core/lib/http/parser.c.orig b/src/core/lib/http/parser.c.orig
new file mode 100644
index 0000000..74d90fd
--- /dev/null
+++ b/src/core/lib/http/parser.c.orig
@@ -0,0 +1,357 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/http/parser.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+int grpc_http1_trace = 0;
+
+static char *buf2str(void *buffer, size_t length) {
+  char *out = gpr_malloc(length + 1);
+  memcpy(out, buffer, length);
+  out[length] = 0;
+  return out;
+}
+
+static grpc_error *handle_response_line(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+
+  if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
+  if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
+  if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'");
+  if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'");
+  if (cur == end || *cur < '0' || *cur++ > '1') {
+    return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1");
+  }
+  if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
+  if (cur == end || *cur < '1' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  if (cur == end || *cur < '0' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  if (cur == end || *cur < '0' || *cur++ > '9')
+    return GRPC_ERROR_CREATE("Expected status code");
+  parser->http.response->status =
+      (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
+  if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
+
+  /* we don't really care about the status code message */
+
+  return GRPC_ERROR_NONE;
+}
+
+static grpc_error *handle_request_line(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+  uint8_t vers_major = 0;
+  uint8_t vers_minor = 0;
+
+  while (cur != end && *cur++ != ' ')
+    ;
+  if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line");
+  parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1));
+
+  beg = cur;
+  while (cur != end && *cur++ != ' ')
+    ;
+  if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line");
+  parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1));
+
+  if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
+  if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
+  if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
+  vers_major = (uint8_t)(*cur++ - '1' + 1);
+  ++cur;
+  if (cur == end)
+    return GRPC_ERROR_CREATE("End of line in HTTP version string");
+  vers_minor = (uint8_t)(*cur++ - '1' + 1);
+
+  if (vers_major == 1) {
+    if (vers_minor == 0) {
+      parser->http.request->version = GRPC_HTTP_HTTP10;
+    } else if (vers_minor == 1) {
+      parser->http.request->version = GRPC_HTTP_HTTP11;
+    } else {
+      return GRPC_ERROR_CREATE(
+          "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
+    }
+  } else if (vers_major == 2) {
+    if (vers_minor == 0) {
+      parser->http.request->version = GRPC_HTTP_HTTP20;
+    } else {
+      return GRPC_ERROR_CREATE(
+          "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
+    }
+  } else {
+    return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
+  }
+
+  return GRPC_ERROR_NONE;
+}
+
+static grpc_error *handle_first_line(grpc_http_parser *parser) {
+  switch (parser->type) {
+    case GRPC_HTTP_REQUEST:
+      return handle_request_line(parser);
+    case GRPC_HTTP_RESPONSE:
+      return handle_response_line(parser);
+  }
+  GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
+}
+
+static grpc_error *add_header(grpc_http_parser *parser) {
+  uint8_t *beg = parser->cur_line;
+  uint8_t *cur = beg;
+  uint8_t *end = beg + parser->cur_line_length;
+  size_t *hdr_count = NULL;
+  grpc_http_header **hdrs = NULL;
+  grpc_http_header hdr = {NULL, NULL};
+  grpc_error *error = GRPC_ERROR_NONE;
+
+  GPR_ASSERT(cur != end);
+
+  if (*cur == ' ' || *cur == '\t') {
+    error = GRPC_ERROR_CREATE("Continued header lines not supported yet");
+    goto done;
+  }
+
+  while (cur != end && *cur != ':') {
+    cur++;
+  }
+  if (cur == end) {
+<<<<<<< HEAD
+    error = GRPC_ERROR_CREATE("Didn't find ':' in header string");
+    goto done;
+=======
+    if (grpc_http1_trace) {
+      gpr_log(GPR_ERROR, "Didn't find ':' in header string");
+    }
+    goto error;
+>>>>>>> a709afe241d8b264a1c326315f757b4a8d330207
+  }
+  GPR_ASSERT(cur >= beg);
+  hdr.key = buf2str(beg, (size_t)(cur - beg));
+  cur++; /* skip : */
+
+  while (cur != end && (*cur == ' ' || *cur == '\t')) {
+    cur++;
+  }
+  GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
+  hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
+
+  switch (parser->type) {
+    case GRPC_HTTP_RESPONSE:
+      hdr_count = &parser->http.response->hdr_count;
+      hdrs = &parser->http.response->hdrs;
+      break;
+    case GRPC_HTTP_REQUEST:
+      hdr_count = &parser->http.request->hdr_count;
+      hdrs = &parser->http.request->hdrs;
+      break;
+  }
+
+  if (*hdr_count == parser->hdr_capacity) {
+    parser->hdr_capacity =
+        GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
+    *hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
+  }
+  (*hdrs)[(*hdr_count)++] = hdr;
+
+done:
+  if (error != GRPC_ERROR_NONE) {
+    gpr_free(hdr.key);
+    gpr_free(hdr.value);
+  }
+  return error;
+}
+
+static grpc_error *finish_line(grpc_http_parser *parser) {
+  grpc_error *err;
+  switch (parser->state) {
+    case GRPC_HTTP_FIRST_LINE:
+      err = handle_first_line(parser);
+      if (err != GRPC_ERROR_NONE) return err;
+      parser->state = GRPC_HTTP_HEADERS;
+      break;
+    case GRPC_HTTP_HEADERS:
+      if (parser->cur_line_length == parser->cur_line_end_length) {
+        parser->state = GRPC_HTTP_BODY;
+        break;
+      }
+      err = add_header(parser);
+      if (err != GRPC_ERROR_NONE) {
+        return err;
+      }
+      break;
+    case GRPC_HTTP_BODY:
+      GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
+  }
+
+  parser->cur_line_length = 0;
+  return GRPC_ERROR_NONE;
+}
+
+static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) {
+  size_t *body_length = NULL;
+  char **body = NULL;
+
+  if (parser->type == GRPC_HTTP_RESPONSE) {
+    body_length = &parser->http.response->body_length;
+    body = &parser->http.response->body;
+  } else if (parser->type == GRPC_HTTP_REQUEST) {
+    body_length = &parser->http.request->body_length;
+    body = &parser->http.request->body;
+  } else {
+    GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
+  }
+
+  if (*body_length == parser->body_capacity) {
+    parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
+    *body = gpr_realloc((void *)*body, parser->body_capacity);
+  }
+  (*body)[*body_length] = (char)byte;
+  (*body_length)++;
+
+  return GRPC_ERROR_NONE;
+}
+
+static bool check_line(grpc_http_parser *parser) {
+  if (parser->cur_line_length >= 2 &&
+      parser->cur_line[parser->cur_line_length - 2] == '\r' &&
+      parser->cur_line[parser->cur_line_length - 1] == '\n') {
+    return true;
+  }
+
+  // HTTP request with \n\r line termiantors.
+  else if (parser->cur_line_length >= 2 &&
+           parser->cur_line[parser->cur_line_length - 2] == '\n' &&
+           parser->cur_line[parser->cur_line_length - 1] == '\r') {
+    return true;
+  }
+
+  // HTTP request with only \n line terminators.
+  else if (parser->cur_line_length >= 1 &&
+           parser->cur_line[parser->cur_line_length - 1] == '\n') {
+    parser->cur_line_end_length = 1;
+    return true;
+  }
+
+  return false;
+}
+
+static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) {
+  switch (parser->state) {
+    case GRPC_HTTP_FIRST_LINE:
+    case GRPC_HTTP_HEADERS:
+      if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
+        if (grpc_http1_trace)
+          gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
+                  GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
+        return 0;
+      }
+      parser->cur_line[parser->cur_line_length] = byte;
+      parser->cur_line_length++;
+      if (check_line(parser)) {
+        return finish_line(parser);
+      } else {
+        return GRPC_ERROR_NONE;
+      }
+      GPR_UNREACHABLE_CODE(return 0);
+    case GRPC_HTTP_BODY:
+      return addbyte_body(parser, byte);
+  }
+  GPR_UNREACHABLE_CODE(return 0);
+}
+
+void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
+                           void *request_or_response) {
+  memset(parser, 0, sizeof(*parser));
+  parser->state = GRPC_HTTP_FIRST_LINE;
+  parser->type = type;
+  parser->http.request_or_response = request_or_response;
+  parser->cur_line_end_length = 2;
+}
+
+void grpc_http_parser_destroy(grpc_http_parser *parser) {}
+
+void grpc_http_request_destroy(grpc_http_request *request) {
+  size_t i;
+  gpr_free(request->body);
+  for (i = 0; i < request->hdr_count; i++) {
+    gpr_free(request->hdrs[i].key);
+    gpr_free(request->hdrs[i].value);
+  }
+  gpr_free(request->hdrs);
+  gpr_free(request->method);
+  gpr_free(request->path);
+}
+
+void grpc_http_response_destroy(grpc_http_response *response) {
+  size_t i;
+  gpr_free(response->body);
+  for (i = 0; i < response->hdr_count; i++) {
+    gpr_free(response->hdrs[i].key);
+    gpr_free(response->hdrs[i].value);
+  }
+  gpr_free(response->hdrs);
+}
+
+grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
+  size_t i;
+
+  for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
+    grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]);
+    if (err != GRPC_ERROR_NONE) return err;
+  }
+
+  return GRPC_ERROR_NONE;
+}
+
+grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) {
+  if (parser->state != GRPC_HTTP_BODY) {
+    return GRPC_ERROR_CREATE("Did not finish headers");
+  }
+  return GRPC_ERROR_NONE;
+}
diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h
index 536637e..6df3cc8 100644
--- a/src/core/lib/http/parser.h
+++ b/src/core/lib/http/parser.h
@@ -36,6 +36,7 @@
 
 #include <grpc/support/port_platform.h>
 #include <grpc/support/slice.h>
+#include "src/core/lib/iomgr/error.h"
 
 /* Maximum length of a header string of the form 'Key: Value\r\n' */
 #define GRPC_HTTP_PARSER_MAX_HEADER_LENGTH 4096
@@ -61,7 +62,6 @@
 typedef enum {
   GRPC_HTTP_RESPONSE,
   GRPC_HTTP_REQUEST,
-  GRPC_HTTP_UNKNOWN
 } grpc_http_type;
 
 /* A request */
@@ -97,8 +97,9 @@
   grpc_http_type type;
 
   union {
-    grpc_http_response response;
-    grpc_http_request request;
+    grpc_http_response *response;
+    grpc_http_request *request;
+    void *request_or_response;
   } http;
   size_t body_capacity;
   size_t hdr_capacity;
@@ -108,11 +109,15 @@
   size_t cur_line_end_length;
 } grpc_http_parser;
 
-void grpc_http_parser_init(grpc_http_parser *parser);
+void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
+                           void *request_or_response);
 void grpc_http_parser_destroy(grpc_http_parser *parser);
 
-int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
-int grpc_http_parser_eof(grpc_http_parser *parser);
+grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
+grpc_error *grpc_http_parser_eof(grpc_http_parser *parser);
+
+void grpc_http_request_destroy(grpc_http_request *request);
+void grpc_http_response_destroy(grpc_http_response *response);
 
 extern int grpc_http1_trace;
 
diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c
index 27793c3..0b6c3b2 100644
--- a/src/core/lib/iomgr/closure.c
+++ b/src/core/lib/iomgr/closure.c
@@ -39,25 +39,32 @@
                        void *cb_arg) {
   closure->cb = cb;
   closure->cb_arg = cb_arg;
-  closure->final_data = 0;
 }
 
-void grpc_closure_list_add(grpc_closure_list *closure_list,
-                           grpc_closure *closure, bool success) {
-  if (closure == NULL) return;
-  closure->final_data = (success != 0);
+void grpc_closure_list_append(grpc_closure_list *closure_list,
+                              grpc_closure *closure, grpc_error *error) {
+  if (closure == NULL) {
+    GRPC_ERROR_UNREF(error);
+    return;
+  }
+  closure->error = error;
+  closure->next_data.next = NULL;
   if (closure_list->head == NULL) {
     closure_list->head = closure;
   } else {
-    closure_list->tail->final_data |= (uintptr_t)closure;
+    closure_list->tail->next_data.next = closure;
   }
   closure_list->tail = closure;
 }
 
-void grpc_closure_list_fail_all(grpc_closure_list *list) {
-  for (grpc_closure *c = list->head; c != NULL; c = grpc_closure_next(c)) {
-    c->final_data &= ~(uintptr_t)1;
+void grpc_closure_list_fail_all(grpc_closure_list *list,
+                                grpc_error *forced_failure) {
+  for (grpc_closure *c = list->head; c != NULL; c = c->next_data.next) {
+    if (c->error == GRPC_ERROR_NONE) {
+      c->error = GRPC_ERROR_REF(forced_failure);
+    }
   }
+  GRPC_ERROR_UNREF(forced_failure);
 }
 
 bool grpc_closure_list_empty(grpc_closure_list closure_list) {
@@ -71,7 +78,7 @@
   if (dst->head == NULL) {
     *dst = *src;
   } else {
-    dst->tail->final_data |= (uintptr_t)src->head;
+    dst->tail->next_data.next = src->head;
     dst->tail = src->tail;
   }
   src->head = src->tail = NULL;
@@ -83,12 +90,13 @@
   grpc_closure wrapper;
 } wrapped_closure;
 
-static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error) {
   wrapped_closure *wc = arg;
   grpc_iomgr_cb_func cb = wc->cb;
   void *cb_arg = wc->cb_arg;
   gpr_free(wc);
-  cb(exec_ctx, cb_arg, success);
+  cb(exec_ctx, cb_arg, error);
 }
 
 grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) {
@@ -98,7 +106,3 @@
   grpc_closure_init(&wc->wrapper, closure_wrapper, wc);
   return &wc->wrapper;
 }
-
-grpc_closure *grpc_closure_next(grpc_closure *closure) {
-  return (grpc_closure *)(closure->final_data & ~(uintptr_t)1);
-}
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index fdc2dae..08e59a1 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -36,6 +36,7 @@
 
 #include <grpc/support/port_platform.h>
 #include <stdbool.h>
+#include "src/core/lib/iomgr/error.h"
 
 struct grpc_closure;
 typedef struct grpc_closure grpc_closure;
@@ -52,10 +53,10 @@
 /** gRPC Callback definition.
  *
  * \param arg Arbitrary input.
- * \param success An indication on the state of the iomgr. On false, cleanup
- * actions should be taken (eg, shutdown). */
+ * \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error
+ *              describing what went wrong */
 typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
-                                   bool success);
+                                   grpc_error *error);
 
 /** A closure over a grpc_iomgr_cb_func. */
 struct grpc_closure {
@@ -65,10 +66,15 @@
   /** Arguments to be passed to "cb". */
   void *cb_arg;
 
-  /** Once enqueued, contains in the lower bit the success of the closure,
-      and in the upper bits the pointer to the next closure in the list.
-      Before enqueing for execution, this is usable for scratch data. */
-  uintptr_t final_data;
+  /** Once queued, the result of the closure. Before then: scratch space */
+  grpc_error *error;
+
+  /** Once queued, next indicates the next queued closure; before then, scratch
+   *  space */
+  union {
+    grpc_closure *next;
+    uintptr_t scratch;
+  } next_data;
 };
 
 /** Initializes \a closure with \a cb and \a cb_arg. */
@@ -81,13 +87,14 @@
 #define GRPC_CLOSURE_LIST_INIT \
   { NULL, NULL }
 
-/** add \a closure to the end of \a list and set \a closure's success to \a
- * success */
-void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
-                           bool success);
+/** add \a closure to the end of \a list
+    and set \a closure's result to \a error */
+void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
+                              grpc_error *error);
 
 /** force all success bits in \a list to false */
-void grpc_closure_list_fail_all(grpc_closure_list *list);
+void grpc_closure_list_fail_all(grpc_closure_list *list,
+                                grpc_error *forced_failure);
 
 /** append all closures from \a src to \a dst and empty \a src. */
 void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
@@ -95,7 +102,4 @@
 /** return whether \a list is empty. */
 bool grpc_closure_list_empty(grpc_closure_list list);
 
-/** return the next pointer for a queued closure list */
-grpc_closure *grpc_closure_next(grpc_closure *closure);
-
 #endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */
diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h
index 3877ceb..f9808bb 100644
--- a/src/core/lib/iomgr/endpoint.h
+++ b/src/core/lib/iomgr/endpoint.h
@@ -82,7 +82,7 @@
 void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                          gpr_slice_buffer *slices, grpc_closure *cb);
 
-/* Causes any pending read/write callbacks to run immediately with
+/* Causes any pending and future read/write callbacks to run immediately with
    success==0 */
 void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
 void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
diff --git a/src/core/lib/iomgr/endpoint_pair_posix.c b/src/core/lib/iomgr/endpoint_pair_posix.c
index e0ce47c..e295fb4 100644
--- a/src/core/lib/iomgr/endpoint_pair_posix.c
+++ b/src/core/lib/iomgr/endpoint_pair_posix.c
@@ -58,8 +58,8 @@
   GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
   flags = fcntl(sv[1], F_GETFL, 0);
   GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE);
 }
 
 grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
new file mode 100644
index 0000000..540fb4f
--- /dev/null
+++ b/src/core/lib/iomgr/error.c
@@ -0,0 +1,535 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/iomgr/error.h"
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/avl.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#ifdef GPR_WINDOWS
+#include <grpc/support/log_windows.h>
+#endif
+
+static void destroy_integer(void *key) {}
+
+static void *copy_integer(void *key) { return key; }
+
+static long compare_integers(void *key1, void *key2) {
+  return GPR_ICMP((uintptr_t)key1, (uintptr_t)key2);
+}
+
+static void destroy_string(void *str) { gpr_free(str); }
+
+static void *copy_string(void *str) { return gpr_strdup(str); }
+
+static void destroy_err(void *err) { GRPC_ERROR_UNREF(err); }
+
+static void *copy_err(void *err) { return GRPC_ERROR_REF(err); }
+
+static void destroy_time(void *tm) { gpr_free(tm); }
+
+static gpr_timespec *box_time(gpr_timespec tm) {
+  gpr_timespec *out = gpr_malloc(sizeof(*out));
+  *out = tm;
+  return out;
+}
+
+static void *copy_time(void *tm) { return box_time(*(gpr_timespec *)tm); }
+
+static const gpr_avl_vtable avl_vtable_ints = {destroy_integer, copy_integer,
+                                               compare_integers,
+                                               destroy_integer, copy_integer};
+
+static const gpr_avl_vtable avl_vtable_strs = {destroy_integer, copy_integer,
+                                               compare_integers, destroy_string,
+                                               copy_string};
+
+static const gpr_avl_vtable avl_vtable_times = {
+    destroy_integer, copy_integer, compare_integers, destroy_time, copy_time};
+
+static const gpr_avl_vtable avl_vtable_errs = {
+    destroy_integer, copy_integer, compare_integers, destroy_err, copy_err};
+
+static const char *error_int_name(grpc_error_ints key) {
+  switch (key) {
+    case GRPC_ERROR_INT_ERRNO:
+      return "errno";
+    case GRPC_ERROR_INT_FILE_LINE:
+      return "file_line";
+    case GRPC_ERROR_INT_STREAM_ID:
+      return "stream_id";
+    case GRPC_ERROR_INT_GRPC_STATUS:
+      return "grpc_status";
+    case GRPC_ERROR_INT_OFFSET:
+      return "offset";
+    case GRPC_ERROR_INT_INDEX:
+      return "index";
+    case GRPC_ERROR_INT_SIZE:
+      return "size";
+    case GRPC_ERROR_INT_HTTP2_ERROR:
+      return "http2_error";
+    case GRPC_ERROR_INT_TSI_CODE:
+      return "tsi_code";
+    case GRPC_ERROR_INT_SECURITY_STATUS:
+      return "security_status";
+    case GRPC_ERROR_INT_FD:
+      return "fd";
+    case GRPC_ERROR_INT_WSA_ERROR:
+      return "wsa_error";
+    case GRPC_ERROR_INT_HTTP_STATUS:
+      return "http_status";
+  }
+  GPR_UNREACHABLE_CODE(return "unknown");
+}
+
+static const char *error_str_name(grpc_error_strs key) {
+  switch (key) {
+    case GRPC_ERROR_STR_DESCRIPTION:
+      return "description";
+    case GRPC_ERROR_STR_OS_ERROR:
+      return "os_error";
+    case GRPC_ERROR_STR_TARGET_ADDRESS:
+      return "target_address";
+    case GRPC_ERROR_STR_SYSCALL:
+      return "syscall";
+    case GRPC_ERROR_STR_FILE:
+      return "file";
+    case GRPC_ERROR_STR_GRPC_MESSAGE:
+      return "grpc_message";
+    case GRPC_ERROR_STR_RAW_BYTES:
+      return "raw_bytes";
+    case GRPC_ERROR_STR_TSI_ERROR:
+      return "tsi_error";
+    case GRPC_ERROR_STR_FILENAME:
+      return "filename";
+  }
+  GPR_UNREACHABLE_CODE(return "unknown");
+}
+
+static const char *error_time_name(grpc_error_times key) {
+  switch (key) {
+    case GRPC_ERROR_TIME_CREATED:
+      return "created";
+  }
+  GPR_UNREACHABLE_CODE(return "unknown");
+}
+
+struct grpc_error {
+  gpr_refcount refs;
+  gpr_avl ints;
+  gpr_avl strs;
+  gpr_avl times;
+  gpr_avl errs;
+  uintptr_t next_err;
+};
+
+static bool is_special(grpc_error *err) {
+  return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM ||
+         err == GRPC_ERROR_CANCELLED;
+}
+
+#ifdef GRPC_ERROR_REFCOUNT_DEBUG
+grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
+                           const char *func) {
+  if (is_special(err)) return err;
+  gpr_log(GPR_DEBUG, "%p: %d -> %d [%s:%d %s]", err, err->refs.count,
+          err->refs.count + 1, file, line, func);
+  gpr_ref(&err->refs);
+  return err;
+}
+#else
+grpc_error *grpc_error_ref(grpc_error *err) {
+  if (is_special(err)) return err;
+  gpr_ref(&err->refs);
+  return err;
+}
+#endif
+
+static void error_destroy(grpc_error *err) {
+  GPR_ASSERT(!is_special(err));
+  gpr_avl_unref(err->ints);
+  gpr_avl_unref(err->strs);
+  gpr_avl_unref(err->errs);
+  gpr_avl_unref(err->times);
+  gpr_free(err);
+}
+
+#ifdef GRPC_ERROR_REFCOUNT_DEBUG
+void grpc_error_unref(grpc_error *err, const char *file, int line,
+                      const char *func) {
+  if (is_special(err)) return;
+  gpr_log(GPR_DEBUG, "%p: %d -> %d [%s:%d %s]", err, err->refs.count,
+          err->refs.count - 1, file, line, func);
+  if (gpr_unref(&err->refs)) {
+    error_destroy(err);
+  }
+}
+#else
+void grpc_error_unref(grpc_error *err) {
+  if (is_special(err)) return;
+  if (gpr_unref(&err->refs)) {
+    error_destroy(err);
+  }
+}
+#endif
+
+grpc_error *grpc_error_create(const char *file, int line, const char *desc,
+                              grpc_error **referencing,
+                              size_t num_referencing) {
+  grpc_error *err = gpr_malloc(sizeof(*err));
+  if (err == NULL) {  // TODO(ctiller): make gpr_malloc return NULL
+    return GRPC_ERROR_OOM;
+  }
+#ifdef GRPC_ERROR_REFCOUNT_DEBUG
+  gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line);
+#endif
+  err->ints = gpr_avl_add(gpr_avl_create(&avl_vtable_ints),
+                          (void *)(uintptr_t)GRPC_ERROR_INT_FILE_LINE,
+                          (void *)(uintptr_t)line);
+  err->strs = gpr_avl_add(
+      gpr_avl_add(gpr_avl_create(&avl_vtable_strs),
+                  (void *)(uintptr_t)GRPC_ERROR_STR_FILE, gpr_strdup(file)),
+      (void *)(uintptr_t)GRPC_ERROR_STR_DESCRIPTION, gpr_strdup(desc));
+  err->errs = gpr_avl_create(&avl_vtable_errs);
+  err->next_err = 0;
+  for (size_t i = 0; i < num_referencing; i++) {
+    if (referencing[i] == GRPC_ERROR_NONE) continue;
+    err->errs = gpr_avl_add(err->errs, (void *)(err->next_err++),
+                            GRPC_ERROR_REF(referencing[i]));
+  }
+  err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
+                           (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
+                           box_time(gpr_now(GPR_CLOCK_REALTIME)));
+  gpr_ref_init(&err->refs, 1);
+  return err;
+}
+
+static grpc_error *copy_error_and_unref(grpc_error *in) {
+  if (is_special(in)) {
+    if (in == GRPC_ERROR_NONE) return GRPC_ERROR_CREATE("no error");
+    if (in == GRPC_ERROR_OOM) return GRPC_ERROR_CREATE("oom");
+    if (in == GRPC_ERROR_CANCELLED) return GRPC_ERROR_CREATE("cancelled");
+    return GRPC_ERROR_CREATE("unknown");
+  }
+  grpc_error *out = gpr_malloc(sizeof(*out));
+#ifdef GRPC_ERROR_REFCOUNT_DEBUG
+  gpr_log(GPR_DEBUG, "%p create copying", out);
+#endif
+  out->ints = gpr_avl_ref(in->ints);
+  out->strs = gpr_avl_ref(in->strs);
+  out->errs = gpr_avl_ref(in->errs);
+  out->times = gpr_avl_ref(in->times);
+  out->next_err = in->next_err;
+  gpr_ref_init(&out->refs, 1);
+  GRPC_ERROR_UNREF(in);
+  return out;
+}
+
+grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
+                               intptr_t value) {
+  grpc_error *new = copy_error_and_unref(src);
+  new->ints = gpr_avl_add(new->ints, (void *)(uintptr_t)which, (void *)value);
+  return new;
+}
+
+bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
+  void *pp;
+  if (gpr_avl_maybe_get(err->ints, (void *)(uintptr_t)which, &pp)) {
+    if (p != NULL) *p = (intptr_t)pp;
+    return true;
+  }
+  return false;
+}
+
+grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
+                               const char *value) {
+  grpc_error *new = copy_error_and_unref(src);
+  new->strs =
+      gpr_avl_add(new->strs, (void *)(uintptr_t)which, gpr_strdup(value));
+  return new;
+}
+
+grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
+  grpc_error *new = copy_error_and_unref(src);
+  new->errs = gpr_avl_add(new->errs, (void *)(new->next_err++), child);
+  return new;
+}
+
+static const char *no_error_string = "null";
+static const char *oom_error_string = "\"Out of memory\"";
+static const char *cancelled_error_string = "\"Cancelled\"";
+
+typedef struct {
+  char *key;
+  char *value;
+} kv_pair;
+
+typedef struct {
+  kv_pair *kvs;
+  size_t num_kvs;
+  size_t cap_kvs;
+} kv_pairs;
+
+static void append_kv(kv_pairs *kvs, char *key, char *value) {
+  if (kvs->num_kvs == kvs->cap_kvs) {
+    kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4);
+    kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs);
+  }
+  kvs->kvs[kvs->num_kvs].key = key;
+  kvs->kvs[kvs->num_kvs].value = value;
+  kvs->num_kvs++;
+}
+
+static void collect_kvs(gpr_avl_node *node, char *key(void *k),
+                        char *fmt(void *v), kv_pairs *kvs) {
+  if (node == NULL) return;
+  append_kv(kvs, key(node->key), fmt(node->value));
+  collect_kvs(node->left, key, fmt, kvs);
+  collect_kvs(node->right, key, fmt, kvs);
+}
+
+static char *key_int(void *p) {
+  return gpr_strdup(error_int_name((grpc_error_ints)(uintptr_t)p));
+}
+
+static char *key_str(void *p) {
+  return gpr_strdup(error_str_name((grpc_error_strs)(uintptr_t)p));
+}
+
+static char *key_time(void *p) {
+  return gpr_strdup(error_time_name((grpc_error_times)(uintptr_t)p));
+}
+
+static char *fmt_int(void *p) {
+  char *s;
+  gpr_asprintf(&s, "%" PRIdPTR, (intptr_t)p);
+  return s;
+}
+
+static void append_chr(char c, char **s, size_t *sz, size_t *cap) {
+  if (*sz == *cap) {
+    *cap = GPR_MAX(8, 3 * *cap / 2);
+    *s = gpr_realloc(*s, *cap);
+  }
+  (*s)[(*sz)++] = c;
+}
+
+static void append_str(const char *str, char **s, size_t *sz, size_t *cap) {
+  for (const char *c = str; *c; c++) {
+    append_chr(*c, s, sz, cap);
+  }
+}
+
+static void append_esc_str(const char *str, char **s, size_t *sz, size_t *cap) {
+  static const char *hex = "0123456789abcdef";
+  append_chr('"', s, sz, cap);
+  for (const uint8_t *c = (const uint8_t *)str; *c; c++) {
+    if (*c < 32 || *c >= 127) {
+      append_chr('\\', s, sz, cap);
+      switch (*c) {
+        case '\b':
+          append_chr('b', s, sz, cap);
+          break;
+        case '\f':
+          append_chr('f', s, sz, cap);
+          break;
+        case '\n':
+          append_chr('n', s, sz, cap);
+          break;
+        case '\r':
+          append_chr('r', s, sz, cap);
+          break;
+        case '\t':
+          append_chr('t', s, sz, cap);
+          break;
+        default:
+          append_chr('u', s, sz, cap);
+          append_chr('0', s, sz, cap);
+          append_chr('0', s, sz, cap);
+          append_chr(hex[*c >> 4], s, sz, cap);
+          append_chr(hex[*c & 0x0f], s, sz, cap);
+          break;
+      }
+    } else {
+      append_chr((char)*c, s, sz, cap);
+    }
+  }
+  append_chr('"', s, sz, cap);
+}
+
+static char *fmt_str(void *p) {
+  char *s = NULL;
+  size_t sz = 0;
+  size_t cap = 0;
+  append_esc_str(p, &s, &sz, &cap);
+  append_chr(0, &s, &sz, &cap);
+  return s;
+}
+
+static char *fmt_time(void *p) {
+  gpr_timespec tm = *(gpr_timespec *)p;
+  char *out;
+  char *pfx = "!!";
+  switch (tm.clock_type) {
+    case GPR_CLOCK_MONOTONIC:
+      pfx = "@monotonic:";
+      break;
+    case GPR_CLOCK_REALTIME:
+      pfx = "@";
+      break;
+    case GPR_CLOCK_PRECISE:
+      pfx = "@precise:";
+      break;
+    case GPR_TIMESPAN:
+      pfx = "";
+      break;
+  }
+  gpr_asprintf(&out, "\"%s%" PRId64 ".%09d\"", pfx, tm.tv_sec, tm.tv_nsec);
+  return out;
+}
+
+static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap) {
+  if (n == NULL) return;
+  add_errs(n->left, s, sz, cap);
+  const char *e = grpc_error_string(n->value);
+  append_str(e, s, sz, cap);
+  grpc_error_free_string(e);
+  add_errs(n->right, s, sz, cap);
+}
+
+static char *errs_string(grpc_error *err) {
+  char *s = NULL;
+  size_t sz = 0;
+  size_t cap = 0;
+  append_chr('[', &s, &sz, &cap);
+  add_errs(err->errs.root, &s, &sz, &cap);
+  append_chr(']', &s, &sz, &cap);
+  append_chr(0, &s, &sz, &cap);
+  return s;
+}
+
+static int cmp_kvs(const void *a, const void *b) {
+  const kv_pair *ka = a;
+  const kv_pair *kb = b;
+  return strcmp(ka->key, kb->key);
+}
+
+static const char *finish_kvs(kv_pairs *kvs) {
+  char *s = NULL;
+  size_t sz = 0;
+  size_t cap = 0;
+
+  append_chr('{', &s, &sz, &cap);
+  for (size_t i = 0; i < kvs->num_kvs; i++) {
+    if (i != 0) append_chr(',', &s, &sz, &cap);
+    append_esc_str(kvs->kvs[i].key, &s, &sz, &cap);
+    gpr_free(kvs->kvs[i].key);
+    append_chr(':', &s, &sz, &cap);
+    append_str(kvs->kvs[i].value, &s, &sz, &cap);
+    gpr_free(kvs->kvs[i].value);
+  }
+  append_chr('}', &s, &sz, &cap);
+  append_chr(0, &s, &sz, &cap);
+
+  gpr_free(kvs->kvs);
+  return s;
+}
+
+void grpc_error_free_string(const char *str) {
+  if (str == no_error_string) return;
+  if (str == oom_error_string) return;
+  if (str == cancelled_error_string) return;
+  gpr_free((char *)str);
+}
+
+const char *grpc_error_string(grpc_error *err) {
+  if (err == GRPC_ERROR_NONE) return no_error_string;
+  if (err == GRPC_ERROR_OOM) return oom_error_string;
+  if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
+
+  kv_pairs kvs;
+  memset(&kvs, 0, sizeof(kvs));
+
+  collect_kvs(err->ints.root, key_int, fmt_int, &kvs);
+  collect_kvs(err->strs.root, key_str, fmt_str, &kvs);
+  collect_kvs(err->times.root, key_time, fmt_time, &kvs);
+  if (!gpr_avl_is_empty(err->errs)) {
+    append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err));
+  }
+
+  qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs);
+
+  return finish_kvs(&kvs);
+}
+
+grpc_error *grpc_os_error(const char *file, int line, int err,
+                          const char *call_name) {
+  return grpc_error_set_str(
+      grpc_error_set_str(
+          grpc_error_set_int(grpc_error_create(file, line, "OS Error", NULL, 0),
+                             GRPC_ERROR_INT_ERRNO, err),
+          GRPC_ERROR_STR_OS_ERROR, strerror(err)),
+      GRPC_ERROR_STR_SYSCALL, call_name);
+}
+
+#ifdef GPR_WINDOWS
+grpc_error *grpc_wsa_error(const char *file, int line, int err,
+                           const char *call_name) {
+  char *utf8_message = gpr_format_message(err);
+  grpc_error *error = grpc_error_set_str(
+      grpc_error_set_str(
+          grpc_error_set_int(grpc_error_create(file, line, "OS Error", NULL, 0),
+                             GRPC_ERROR_INT_WSA_ERROR, err),
+          GRPC_ERROR_STR_OS_ERROR, utf8_message),
+      GRPC_ERROR_STR_SYSCALL, call_name);
+  gpr_free(utf8_message);
+  return error;
+}
+#endif
+
+bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
+                       int line) {
+  if (error == GRPC_ERROR_NONE) return true;
+  const char *msg = grpc_error_string(error);
+  gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg);
+  grpc_error_free_string(msg);
+  GRPC_ERROR_UNREF(error);
+  return false;
+}
diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h
new file mode 100644
index 0000000..69cdf30
--- /dev/null
+++ b/src/core/lib/iomgr/error.h
@@ -0,0 +1,192 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_ERROR_H
+#define GRPC_CORE_LIB_IOMGR_ERROR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <grpc/support/time.h>
+
+/// Opaque representation of an error.
+/// Errors are refcounted objects that represent the result of an operation.
+/// Ownership laws:
+///  if a grpc_error is returned by a function, the caller owns a ref to that
+///    instance
+///  if a grpc_error is passed to a grpc_closure callback function (functions
+///    with the signature:
+///      void (*f)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error))
+///    then those functions do not automatically own a ref to error
+///  if a grpc_error is passed to *ANY OTHER FUNCTION* then that function takes
+///    ownership of the error
+/// Errors have:
+///  a set of ints, strings, and timestamps that describe the error
+///  always present are:
+///    GRPC_ERROR_STR_FILE, GRPC_ERROR_INT_FILE_LINE - source location the error
+///      was generated
+///    GRPC_ERROR_STR_DESCRIPTION - a human readable description of the error
+///    GRPC_ERROR_TIME_CREATED - a timestamp indicating when the error happened
+///  an error can also have children; these are other errors that are believed
+///    to have contributed to this one. By accumulating children, we can begin
+///    to root cause high level failures from low level failures, without having
+///    to derive execution paths from log lines
+typedef struct grpc_error grpc_error;
+
+typedef enum {
+  /// 'errno' from the operating system
+  GRPC_ERROR_INT_ERRNO,
+  /// __LINE__ from the call site creating the error
+  GRPC_ERROR_INT_FILE_LINE,
+  /// stream identifier: for errors that are associated with an individual
+  /// wire stream
+  GRPC_ERROR_INT_STREAM_ID,
+  /// grpc status code representing this error
+  GRPC_ERROR_INT_GRPC_STATUS,
+  /// offset into some binary blob (usually represented by
+  /// GRPC_ERROR_STR_RAW_BYTES) where the error occurred
+  GRPC_ERROR_INT_OFFSET,
+  /// context sensitive index associated with the error
+  GRPC_ERROR_INT_INDEX,
+  /// context sensitive size associated with the error
+  GRPC_ERROR_INT_SIZE,
+  /// http2 error code associated with the error (see the HTTP2 RFC)
+  GRPC_ERROR_INT_HTTP2_ERROR,
+  /// TSI status code associated with the error
+  GRPC_ERROR_INT_TSI_CODE,
+  /// grpc_security_status associated with the error
+  GRPC_ERROR_INT_SECURITY_STATUS,
+  /// WSAGetLastError() reported when this error occurred
+  GRPC_ERROR_INT_WSA_ERROR,
+  /// File descriptor associated with this error
+  GRPC_ERROR_INT_FD,
+  /// HTTP status (i.e. 404)
+  GRPC_ERROR_INT_HTTP_STATUS,
+} grpc_error_ints;
+
+typedef enum {
+  /// top-level textual description of this error
+  GRPC_ERROR_STR_DESCRIPTION,
+  /// source file in which this error occurred
+  GRPC_ERROR_STR_FILE,
+  /// operating system description of this error
+  GRPC_ERROR_STR_OS_ERROR,
+  /// syscall that generated this error
+  GRPC_ERROR_STR_SYSCALL,
+  /// peer that we were trying to communicate when this error occurred
+  GRPC_ERROR_STR_TARGET_ADDRESS,
+  /// grpc status message associated with this error
+  GRPC_ERROR_STR_GRPC_MESSAGE,
+  /// hex dump (or similar) with the data that generated this error
+  GRPC_ERROR_STR_RAW_BYTES,
+  /// tsi error string associated with this error
+  GRPC_ERROR_STR_TSI_ERROR,
+  /// filename that we were trying to read/write when this error occurred
+  GRPC_ERROR_STR_FILENAME,
+} grpc_error_strs;
+
+typedef enum {
+  /// timestamp of error creation
+  GRPC_ERROR_TIME_CREATED,
+} grpc_error_times;
+
+#define GRPC_ERROR_NONE ((grpc_error *)NULL)
+#define GRPC_ERROR_OOM ((grpc_error *)1)
+#define GRPC_ERROR_CANCELLED ((grpc_error *)2)
+
+const char *grpc_error_string(grpc_error *error);
+void grpc_error_free_string(const char *str);
+
+/// Create an error - but use GRPC_ERROR_CREATE instead
+grpc_error *grpc_error_create(const char *file, int line, const char *desc,
+                              grpc_error **referencing, size_t num_referencing);
+/// Create an error (this is the preferred way of generating an error that is
+///   not due to a system call - for system calls, use GRPC_OS_ERROR or
+///   GRPC_WSA_ERROR as appropriate)
+/// \a referencing is an array of num_referencing elements indicating one or
+/// more errors that are believed to have contributed to this one
+/// err = grpc_error_create(x, y, z, r, nr) is equivalent to:
+///   err = grpc_error_create(x, y, z, NULL, 0);
+///   for (i=0; i<nr; i++) err = grpc_error_add_child(err, r[i]);
+#define GRPC_ERROR_CREATE(desc) \
+  grpc_error_create(__FILE__, __LINE__, desc, NULL, 0)
+
+// Create an error that references some other errors. This function adds a
+// reference to each error in errs - it does not consume an existing reference
+#define GRPC_ERROR_CREATE_REFERENCING(desc, errs, count) \
+  grpc_error_create(__FILE__, __LINE__, desc, errs, count)
+
+//#define GRPC_ERROR_REFCOUNT_DEBUG
+#ifdef GRPC_ERROR_REFCOUNT_DEBUG
+grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
+                           const char *func);
+void grpc_error_unref(grpc_error *err, const char *file, int line,
+                      const char *func);
+#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__, __func__)
+#define GRPC_ERROR_UNREF(err) \
+  grpc_error_unref(err, __FILE__, __LINE__, __func__)
+#else
+grpc_error *grpc_error_ref(grpc_error *err);
+void grpc_error_unref(grpc_error *err);
+#define GRPC_ERROR_REF(err) grpc_error_ref(err)
+#define GRPC_ERROR_UNREF(err) grpc_error_unref(err)
+#endif
+
+grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
+                               intptr_t value);
+bool grpc_error_get_int(grpc_error *error, grpc_error_ints which, intptr_t *p);
+grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which,
+                                gpr_timespec value);
+grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
+                               const char *value);
+/// Add a child error: an error that is believed to have contributed to this
+/// error occurring. Allows root causing high level errors from lower level
+/// errors that contributed to them.
+grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child);
+grpc_error *grpc_os_error(const char *file, int line, int err,
+                          const char *call_name);
+/// create an error associated with errno!=0 (an 'operating system' error)
+#define GRPC_OS_ERROR(err, call_name) \
+  grpc_os_error(__FILE__, __LINE__, err, call_name)
+grpc_error *grpc_wsa_error(const char *file, int line, int err,
+                           const char *call_name);
+/// windows only: create an error associated with WSAGetLastError()!=0
+#define GRPC_WSA_ERROR(err, call_name) \
+  grpc_wsa_error(__FILE__, __LINE__, err, call_name)
+
+bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
+                       int line);
+#define GRPC_LOG_IF_ERROR(what, error) \
+  grpc_log_if_error((what), (error), __FILE__, __LINE__)
+
+#endif /* GRPC_CORE_LIB_IOMGR_ERROR_H */
diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
index 943c404..9e306af 100644
--- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c
@@ -221,9 +221,10 @@
 struct grpc_pollset_vtable {
   void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                  struct grpc_fd *fd, int and_unlock_pollset);
-  void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                                grpc_pollset_worker *worker,
-                                gpr_timespec deadline, gpr_timespec now);
+  grpc_error *(*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx,
+                                       grpc_pollset *pollset,
+                                       grpc_pollset_worker *worker,
+                                       gpr_timespec deadline, gpr_timespec now);
   void (*finish_shutdown)(grpc_pollset *pollset);
   void (*destroy)(grpc_pollset *pollset);
 };
@@ -251,9 +252,9 @@
 #define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2
 /* As per pollset_kick, with an extended set of flags (defined above)
    -- mostly for fd_posix's use. */
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags);
+static grpc_error *pollset_kick_ext(grpc_pollset *p,
+                                    grpc_pollset_worker *specific_worker,
+                                    uint32_t flags) GRPC_MUST_USE_RESULT;
 
 /* turn a pollset into a multipoller: platform specific */
 typedef void (*platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx,
@@ -420,12 +421,13 @@
   return (gpr_atm_acq_load(&fd->refst) & 1) == 0;
 }
 
-static void pollset_kick_locked(grpc_fd_watcher *watcher) {
+static grpc_error *pollset_kick_locked(grpc_fd_watcher *watcher) {
   gpr_mu_lock(&watcher->pollset->mu);
   GPR_ASSERT(watcher->worker);
-  pollset_kick_ext(watcher->pollset, watcher->worker,
-                   GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
+  grpc_error *err = pollset_kick_ext(watcher->pollset, watcher->worker,
+                                     GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
   gpr_mu_unlock(&watcher->pollset->mu);
+  return err;
 }
 
 static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
@@ -464,7 +466,7 @@
   } else {
     remove_fd_from_all_epoll_sets(fd->fd);
   }
-  grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE, NULL);
 }
 
 static int fd_wrapped_fd(grpc_fd *fd) {
@@ -513,15 +515,27 @@
 static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
 #endif
 
+static grpc_error *fd_shutdown_error(bool shutdown) {
+  if (!shutdown) {
+    return GRPC_ERROR_NONE;
+  } else {
+    return GRPC_ERROR_CREATE("FD shutdown");
+  }
+}
+
 static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                              grpc_closure **st, grpc_closure *closure) {
-  if (*st == CLOSURE_NOT_READY) {
+  if (fd->shutdown) {
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"),
+                        NULL);
+  } else if (*st == CLOSURE_NOT_READY) {
     /* not ready ==> switch to a waiting state by setting the closure */
     *st = closure;
   } else if (*st == CLOSURE_READY) {
     /* already ready ==> queue the closure to run immediately */
     *st = CLOSURE_NOT_READY;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown),
+                        NULL);
     maybe_wake_one_watcher_locked(fd);
   } else {
     /* upcallptr was set to a different closure.  This is an error! */
@@ -544,7 +558,7 @@
     return 0;
   } else {
     /* waiting ==> queue closure */
-    grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL);
+    grpc_exec_ctx_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown), NULL);
     *st = CLOSURE_NOT_READY;
     return 1;
   }
@@ -557,13 +571,24 @@
 
 static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
   gpr_mu_lock(&fd->mu);
-  GPR_ASSERT(!fd->shutdown);
-  fd->shutdown = 1;
-  set_ready_locked(exec_ctx, fd, &fd->read_closure);
-  set_ready_locked(exec_ctx, fd, &fd->write_closure);
+  /* only shutdown once */
+  if (!fd->shutdown) {
+    fd->shutdown = 1;
+    /* signal read/write closed to OS so that future operations fail */
+    shutdown(fd->fd, SHUT_RDWR);
+    set_ready_locked(exec_ctx, fd, &fd->read_closure);
+    set_ready_locked(exec_ctx, fd, &fd->write_closure);
+  }
   gpr_mu_unlock(&fd->mu);
 }
 
+static bool fd_is_shutdown(grpc_fd *fd) {
+  gpr_mu_lock(&fd->mu);
+  bool r = fd->shutdown;
+  gpr_mu_unlock(&fd->mu);
+  return r;
+}
+
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
   gpr_mu_lock(&fd->mu);
@@ -744,10 +769,19 @@
   worker->prev->next = worker->next->prev = worker;
 }
 
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags) {
+static void kick_append_error(grpc_error **composite, grpc_error *error) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE) {
+    *composite = GRPC_ERROR_CREATE("Kick Failure");
+  }
+  *composite = grpc_error_add_child(*composite, error);
+}
+
+static grpc_error *pollset_kick_ext(grpc_pollset *p,
+                                    grpc_pollset_worker *specific_worker,
+                                    uint32_t flags) {
   GPR_TIMER_BEGIN("pollset_kick_ext", 0);
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* pollset->mu already held */
   if (specific_worker != NULL) {
@@ -757,25 +791,28 @@
       for (specific_worker = p->root_worker.next;
            specific_worker != &p->root_worker;
            specific_worker = specific_worker->next) {
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+        kick_append_error(
+            &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
       }
-      p->kicked_without_pollers = 1;
+      p->kicked_without_pollers = true;
       GPR_TIMER_END("pollset_kick_ext.broadcast", 0);
     } else if (gpr_tls_get(&g_current_thread_worker) !=
                (intptr_t)specific_worker) {
       GPR_TIMER_MARK("different_thread_worker", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
+        specific_worker->reevaluate_polling_on_wakeup = true;
       }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+      specific_worker->kicked_specifically = true;
+      kick_append_error(&error,
+                        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
     } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
       GPR_TIMER_MARK("kick_yoself", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
+        specific_worker->reevaluate_polling_on_wakeup = true;
       }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+      specific_worker->kicked_specifically = true;
+      kick_append_error(&error,
+                        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
     }
   } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
     GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
@@ -783,14 +820,9 @@
     specific_worker = pop_front_worker(p);
     if (specific_worker != NULL) {
       if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
-        /* Prefer not to kick self. Push the worker to the end of the list and
-         * pop the one from front */
         GPR_TIMER_MARK("kick_anonymous_not_self", 0);
         push_back_worker(p, specific_worker);
         specific_worker = pop_front_worker(p);
-        /* If there was only one worker on the pollset, we would get the same
-         * worker we pushed (the one set on current thread local) back. If so,
-         * kick it only if GRPC_POLLSET_CAN_KICK_SELF flag is set */
         if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 &&
             gpr_tls_get(&g_current_thread_worker) ==
                 (intptr_t)specific_worker) {
@@ -801,28 +833,30 @@
       if (specific_worker != NULL) {
         GPR_TIMER_MARK("finally_kick", 0);
         push_back_worker(p, specific_worker);
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+        kick_append_error(
+            &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
       }
     } else {
       GPR_TIMER_MARK("kicked_no_pollers", 0);
-      p->kicked_without_pollers = 1;
+      p->kicked_without_pollers = true;
     }
   }
 
   GPR_TIMER_END("pollset_kick_ext", 0);
+  return error;
 }
 
-static void pollset_kick(grpc_pollset *p,
-                         grpc_pollset_worker *specific_worker) {
-  pollset_kick_ext(p, specific_worker, 0);
+static grpc_error *pollset_kick(grpc_pollset *p,
+                                grpc_pollset_worker *specific_worker) {
+  return pollset_kick_ext(p, specific_worker, 0);
 }
 
 /* global state management */
 
-static void pollset_global_init(void) {
+static grpc_error *pollset_global_init(void) {
   gpr_tls_init(&g_current_thread_poller);
   gpr_tls_init(&g_current_thread_worker);
-  grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
+  return grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
 }
 
 static void pollset_global_shutdown(void) {
@@ -831,7 +865,9 @@
   gpr_tls_destroy(&g_current_thread_worker);
 }
 
-static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
+static grpc_error *kick_poller(void) {
+  return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
+}
 
 /* main interface */
 
@@ -894,14 +930,23 @@
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
   GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs));
   pollset->vtable->finish_shutdown(pollset);
-  grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL);
 }
 
-static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         grpc_pollset_worker **worker_hdl, gpr_timespec now,
-                         gpr_timespec deadline) {
+static void work_combine_error(grpc_error **composite, grpc_error *error) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE) {
+    *composite = GRPC_ERROR_CREATE("pollset_work");
+  }
+  *composite = grpc_error_add_child(*composite, error);
+}
+
+static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                                grpc_pollset_worker **worker_hdl,
+                                gpr_timespec now, gpr_timespec deadline) {
   grpc_pollset_worker worker;
   *worker_hdl = &worker;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* pollset->mu already held */
   int added_worker = 0;
@@ -917,7 +962,10 @@
     pollset->local_wakeup_cache = worker.wakeup_fd->next;
   } else {
     worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
-    grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
+    error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
+    if (error != GRPC_ERROR_NONE) {
+      return error;
+    }
   }
   worker.kicked_specifically = 0;
   /* If there's work waiting for the pollset to be idle, and the
@@ -954,8 +1002,9 @@
       }
       gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset);
       GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
-      pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker,
-                                             deadline, now);
+      work_combine_error(&error,
+                         pollset->vtable->maybe_work_and_unlock(
+                             exec_ctx, pollset, &worker, deadline, now));
       GPR_TIMER_END("maybe_work_and_unlock", 0);
       locked = 0;
       gpr_tls_set(&g_current_thread_poller, 0);
@@ -1017,6 +1066,7 @@
   }
   *worker_hdl = NULL;
   GPR_TIMER_END("pollset_work", 0);
+  return error;
 }
 
 static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -1065,7 +1115,7 @@
 } grpc_unary_promote_args;
 
 static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args,
-                             bool success) {
+                             grpc_error *error) {
   grpc_unary_promote_args *up_args = args;
   const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
   grpc_pollset *pollset = up_args->pollset;
@@ -1167,7 +1217,8 @@
   up_args->promotion_closure.cb = basic_do_promote;
   up_args->promotion_closure.cb_arg = up_args;
 
-  grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1);
+  grpc_closure_list_append(&pollset->idle_jobs, &up_args->promotion_closure,
+                           GRPC_ERROR_NONE);
   pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
 
 exit:
@@ -1176,11 +1227,9 @@
   }
 }
 
-static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
-                                                grpc_pollset *pollset,
-                                                grpc_pollset_worker *worker,
-                                                gpr_timespec deadline,
-                                                gpr_timespec now) {
+static grpc_error *basic_pollset_maybe_work_and_unlock(
+    grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
+    gpr_timespec deadline, gpr_timespec now) {
 #define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
 #define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR)
 
@@ -1190,6 +1239,7 @@
   int timeout;
   int r;
   nfds_t nfds;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   fd = pollset->data.ptr;
   if (fd && fd_is_orphaned(fd)) {
@@ -1230,7 +1280,7 @@
 
   if (r < 0) {
     if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+      work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
     }
     if (fd) {
       fd_end_poll(exec_ctx, &fd_watcher, 0, 0, NULL);
@@ -1241,10 +1291,12 @@
     }
   } else {
     if (pfd[0].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+      work_combine_error(&error,
+                         grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
     }
     if (pfd[1].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
+      work_combine_error(&error,
+                         grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
     }
     if (nfds > 2) {
       fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK,
@@ -1257,6 +1309,8 @@
   if (fd) {
     GRPC_FD_UNREF(fd, "basicpoll_begin");
   }
+
+  return error;
 }
 
 static void basic_pollset_destroy(grpc_pollset *pollset) {
@@ -1317,7 +1371,7 @@
   }
 }
 
-static void multipoll_with_poll_pollset_maybe_work_and_unlock(
+static grpc_error *multipoll_with_poll_pollset_maybe_work_and_unlock(
     grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
     gpr_timespec deadline, gpr_timespec now) {
 #define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
@@ -1331,6 +1385,7 @@
   /* TODO(ctiller): inline some elements to avoid an allocation */
   grpc_fd_watcher *watchers;
   struct pollfd *pfds;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   h = pollset->data.ptr;
   timeout = poll_deadline_to_millis_timeout(deadline, now);
@@ -1383,7 +1438,7 @@
 
   if (r < 0) {
     if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+      work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
     }
     for (i = 2; i < pfd_count; i++) {
       fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
@@ -1394,10 +1449,12 @@
     }
   } else {
     if (pfds[0].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+      work_combine_error(&error,
+                         grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
     }
     if (pfds[1].revents & POLLIN_CHECK) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
+      work_combine_error(&error,
+                         grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
     }
     for (i = 2; i < pfd_count; i++) {
       if (watchers[i].fd == NULL) {
@@ -1411,6 +1468,8 @@
 
   gpr_free(pfds);
   gpr_free(watchers);
+
+  return error;
 }
 
 static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) {
@@ -1601,7 +1660,7 @@
 }
 
 static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg,
-                                bool iomgr_status) {
+                                grpc_error *error) {
   delayed_add *da = arg;
 
   if (!fd_is_orphaned(da->fd)) {
@@ -1614,7 +1673,8 @@
     /* We don't care about this pollset anymore. */
     if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) {
       da->pollset->called_shutdown = 1;
-      grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, da->pollset->shutdown_done, GRPC_ERROR_NONE,
+                          NULL);
     }
   }
   gpr_mu_unlock(&da->pollset->mu);
@@ -1638,14 +1698,14 @@
     GRPC_FD_REF(fd, "delayed_add");
     grpc_closure_init(&da->closure, perform_delayed_add, da);
     pollset->in_flight_cbs++;
-    grpc_exec_ctx_enqueue(exec_ctx, &da->closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &da->closure, GRPC_ERROR_NONE, NULL);
   }
 }
 
 /* TODO(klempner): We probably want to turn this down a bit */
 #define GRPC_EPOLL_MAX_EVENTS 1000
 
-static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
+static grpc_error *multipoll_with_epoll_pollset_maybe_work_and_unlock(
     grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
     gpr_timespec deadline, gpr_timespec now) {
   struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS];
@@ -1654,6 +1714,7 @@
   epoll_hdr *h = pollset->data.ptr;
   int timeout_ms;
   struct pollfd pfds[2];
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* If you want to ignore epoll's ability to sanely handle parallel pollers,
    * for a more apples-to-apples performance comparison with poll, add a
@@ -1682,13 +1743,14 @@
 
   if (poll_rv < 0) {
     if (errno != EINTR) {
-      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+      work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
     }
   } else if (poll_rv == 0) {
     /* do nothing */
   } else {
     if (pfds[0].revents) {
-      grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
+      work_combine_error(&error,
+                         grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
     }
     if (pfds[1].revents) {
       do {
@@ -1696,7 +1758,7 @@
         ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0);
         if (ep_rv < 0) {
           if (errno != EINTR) {
-            gpr_log(GPR_ERROR, "epoll_wait() failed: %s", strerror(errno));
+            work_combine_error(&error, GRPC_OS_ERROR(errno, "epoll_wait"));
           }
         } else {
           int i;
@@ -1708,7 +1770,8 @@
             int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI);
             int write_ev = ep_ev[i].events & EPOLLOUT;
             if (fd == NULL) {
-              grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+              work_combine_error(&error, grpc_wakeup_fd_consume_wakeup(
+                                             &grpc_global_wakeup_fd));
             } else {
               if (read_ev || cancel) {
                 fd_become_readable(exec_ctx, fd, pollset);
@@ -1722,6 +1785,7 @@
       } while (ep_rv == GRPC_EPOLL_MAX_EVENTS);
     }
   }
+  return error;
 }
 
 static void multipoll_with_epoll_pollset_finish_shutdown(
@@ -1938,6 +2002,7 @@
     .fd_wrapped_fd = fd_wrapped_fd,
     .fd_orphan = fd_orphan,
     .fd_shutdown = fd_shutdown,
+    .fd_is_shutdown = fd_is_shutdown,
     .fd_notify_on_read = fd_notify_on_read,
     .fd_notify_on_write = fd_notify_on_write,
     .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index 0167999..45c0a5e 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
+ * Copyright 2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -217,9 +217,9 @@
 #define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2
 /* As per pollset_kick, with an extended set of flags (defined above)
    -- mostly for fd_posix's use. */
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags);
+static grpc_error *pollset_kick_ext(grpc_pollset *p,
+                                    grpc_pollset_worker *specific_worker,
+                                    uint32_t flags) GRPC_MUST_USE_RESULT;
 
 /* Return 1 if the pollset has active threads in pollset_work (pollset must
  * be locked) */
@@ -328,12 +328,13 @@
   return notifier;
 }
 
-static void pollset_kick_locked(grpc_fd_watcher *watcher) {
+static grpc_error *pollset_kick_locked(grpc_fd_watcher *watcher) {
   gpr_mu_lock(&watcher->pollset->mu);
   GPR_ASSERT(watcher->worker);
-  pollset_kick_ext(watcher->pollset, watcher->worker,
-                   GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
+  grpc_error *err = pollset_kick_ext(watcher->pollset, watcher->worker,
+                                     GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
   gpr_mu_unlock(&watcher->pollset->mu);
+  return err;
 }
 
 static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
@@ -370,7 +371,7 @@
   if (!fd->released) {
     close(fd->fd);
   }
-  grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE, NULL);
 }
 
 static int fd_wrapped_fd(grpc_fd *fd) {
@@ -419,15 +420,27 @@
 static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
 #endif
 
+static grpc_error *fd_shutdown_error(bool shutdown) {
+  if (!shutdown) {
+    return GRPC_ERROR_NONE;
+  } else {
+    return GRPC_ERROR_CREATE("FD shutdown");
+  }
+}
+
 static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                              grpc_closure **st, grpc_closure *closure) {
-  if (*st == CLOSURE_NOT_READY) {
+  if (fd->shutdown) {
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"),
+                        NULL);
+  } else if (*st == CLOSURE_NOT_READY) {
     /* not ready ==> switch to a waiting state by setting the closure */
     *st = closure;
   } else if (*st == CLOSURE_READY) {
     /* already ready ==> queue the closure to run immediately */
     *st = CLOSURE_NOT_READY;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown),
+                        NULL);
     maybe_wake_one_watcher_locked(fd);
   } else {
     /* upcallptr was set to a different closure.  This is an error! */
@@ -450,7 +463,7 @@
     return 0;
   } else {
     /* waiting ==> queue closure */
-    grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL);
+    grpc_exec_ctx_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown), NULL);
     *st = CLOSURE_NOT_READY;
     return 1;
   }
@@ -463,13 +476,24 @@
 
 static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
   gpr_mu_lock(&fd->mu);
-  GPR_ASSERT(!fd->shutdown);
-  fd->shutdown = 1;
-  set_ready_locked(exec_ctx, fd, &fd->read_closure);
-  set_ready_locked(exec_ctx, fd, &fd->write_closure);
+  /* only shutdown once */
+  if (!fd->shutdown) {
+    fd->shutdown = 1;
+    /* signal read/write closed to OS so that future operations fail */
+    shutdown(fd->fd, SHUT_RDWR);
+    set_ready_locked(exec_ctx, fd, &fd->read_closure);
+    set_ready_locked(exec_ctx, fd, &fd->write_closure);
+  }
   gpr_mu_unlock(&fd->mu);
 }
 
+static bool fd_is_shutdown(grpc_fd *fd) {
+  gpr_mu_lock(&fd->mu);
+  bool r = fd->shutdown;
+  gpr_mu_unlock(&fd->mu);
+  return r;
+}
+
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
   gpr_mu_lock(&fd->mu);
@@ -631,10 +655,19 @@
   worker->prev->next = worker->next->prev = worker;
 }
 
-static void pollset_kick_ext(grpc_pollset *p,
-                             grpc_pollset_worker *specific_worker,
-                             uint32_t flags) {
+static void kick_append_error(grpc_error **composite, grpc_error *error) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE) {
+    *composite = GRPC_ERROR_CREATE("Kick Failure");
+  }
+  *composite = grpc_error_add_child(*composite, error);
+}
+
+static grpc_error *pollset_kick_ext(grpc_pollset *p,
+                                    grpc_pollset_worker *specific_worker,
+                                    uint32_t flags) {
   GPR_TIMER_BEGIN("pollset_kick_ext", 0);
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* pollset->mu already held */
   if (specific_worker != NULL) {
@@ -644,25 +677,28 @@
       for (specific_worker = p->root_worker.next;
            specific_worker != &p->root_worker;
            specific_worker = specific_worker->next) {
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+        kick_append_error(
+            &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
       }
-      p->kicked_without_pollers = 1;
+      p->kicked_without_pollers = true;
       GPR_TIMER_END("pollset_kick_ext.broadcast", 0);
     } else if (gpr_tls_get(&g_current_thread_worker) !=
                (intptr_t)specific_worker) {
       GPR_TIMER_MARK("different_thread_worker", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
+        specific_worker->reevaluate_polling_on_wakeup = true;
       }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+      specific_worker->kicked_specifically = true;
+      kick_append_error(&error,
+                        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
     } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
       GPR_TIMER_MARK("kick_yoself", 0);
       if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
-        specific_worker->reevaluate_polling_on_wakeup = 1;
+        specific_worker->reevaluate_polling_on_wakeup = true;
       }
-      specific_worker->kicked_specifically = 1;
-      grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+      specific_worker->kicked_specifically = true;
+      kick_append_error(&error,
+                        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
     }
   } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
     GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
@@ -683,28 +719,31 @@
       if (specific_worker != NULL) {
         GPR_TIMER_MARK("finally_kick", 0);
         push_back_worker(p, specific_worker);
-        grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
+        kick_append_error(
+            &error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
       }
     } else {
       GPR_TIMER_MARK("kicked_no_pollers", 0);
-      p->kicked_without_pollers = 1;
+      p->kicked_without_pollers = true;
     }
   }
 
   GPR_TIMER_END("pollset_kick_ext", 0);
+  GRPC_LOG_IF_ERROR("pollset_kick_ext", GRPC_ERROR_REF(error));
+  return error;
 }
 
-static void pollset_kick(grpc_pollset *p,
-                         grpc_pollset_worker *specific_worker) {
-  pollset_kick_ext(p, specific_worker, 0);
+static grpc_error *pollset_kick(grpc_pollset *p,
+                                grpc_pollset_worker *specific_worker) {
+  return pollset_kick_ext(p, specific_worker, 0);
 }
 
 /* global state management */
 
-static void pollset_global_init(void) {
+static grpc_error *pollset_global_init(void) {
   gpr_tls_init(&g_current_thread_poller);
   gpr_tls_init(&g_current_thread_worker);
-  grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
+  return grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
 }
 
 static void pollset_global_shutdown(void) {
@@ -713,7 +752,9 @@
   gpr_tls_destroy(&g_current_thread_worker);
 }
 
-static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
+static grpc_error *kick_poller(void) {
+  return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
+}
 
 /* main interface */
 
@@ -783,14 +824,23 @@
     GRPC_FD_UNREF(pollset->fds[i], "multipoller");
   }
   pollset->fd_count = 0;
-  grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL);
 }
 
-static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         grpc_pollset_worker **worker_hdl, gpr_timespec now,
-                         gpr_timespec deadline) {
+static void work_combine_error(grpc_error **composite, grpc_error *error) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE) {
+    *composite = GRPC_ERROR_CREATE("pollset_work");
+  }
+  *composite = grpc_error_add_child(*composite, error);
+}
+
+static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                                grpc_pollset_worker **worker_hdl,
+                                gpr_timespec now, gpr_timespec deadline) {
   grpc_pollset_worker worker;
   *worker_hdl = &worker;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* pollset->mu already held */
   int added_worker = 0;
@@ -806,7 +856,11 @@
     pollset->local_wakeup_cache = worker.wakeup_fd->next;
   } else {
     worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
-    grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
+    error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
+    if (error != GRPC_ERROR_NONE) {
+      GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
+      return error;
+    }
   }
   worker.kicked_specifically = 0;
   /* If there's work waiting for the pollset to be idle, and the
@@ -890,7 +944,7 @@
 
       if (r < 0) {
         if (errno != EINTR) {
-          gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+          work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
         }
         for (i = 2; i < pfd_count; i++) {
           fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
@@ -901,10 +955,12 @@
         }
       } else {
         if (pfds[0].revents & POLLIN_CHECK) {
-          grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+          work_combine_error(
+              &error, grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
         }
         if (pfds[1].revents & POLLIN_CHECK) {
-          grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd);
+          work_combine_error(
+              &error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd));
         }
         for (i = 2; i < pfd_count; i++) {
           if (watchers[i].fd == NULL) {
@@ -937,7 +993,7 @@
     /* If we're forced to re-evaluate polling (via pollset_kick with
        GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force
        a loop */
-    if (worker.reevaluate_polling_on_wakeup) {
+    if (worker.reevaluate_polling_on_wakeup && error == GRPC_ERROR_NONE) {
       worker.reevaluate_polling_on_wakeup = 0;
       pollset->kicked_without_pollers = 0;
       if (queued_work || worker.kicked_specifically) {
@@ -982,6 +1038,8 @@
   }
   *worker_hdl = NULL;
   GPR_TIMER_END("pollset_work", 0);
+  GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
+  return error;
 }
 
 static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -1172,6 +1230,7 @@
     .fd_wrapped_fd = fd_wrapped_fd,
     .fd_orphan = fd_orphan,
     .fd_shutdown = fd_shutdown,
+    .fd_is_shutdown = fd_is_shutdown,
     .fd_notify_on_read = fd_notify_on_read,
     .fd_notify_on_write = fd_notify_on_write,
     .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
@@ -1199,7 +1258,9 @@
 };
 
 const grpc_event_engine_vtable *grpc_init_poll_posix(void) {
-  pollset_global_init();
+  if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
+    return NULL;
+  }
   return &vtable;
 }
 
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index 6477b05..4c360f1 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -153,6 +153,10 @@
   g_event_engine->fd_shutdown(exec_ctx, fd);
 }
 
+bool grpc_fd_is_shutdown(grpc_fd *fd) {
+  return g_event_engine->fd_is_shutdown(fd);
+}
+
 void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                             grpc_closure *closure) {
   g_event_engine->fd_notify_on_read(exec_ctx, fd, closure);
@@ -187,15 +191,15 @@
   g_event_engine->pollset_destroy(pollset);
 }
 
-void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker **worker, gpr_timespec now,
-                       gpr_timespec deadline) {
-  g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline);
+grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                              grpc_pollset_worker **worker, gpr_timespec now,
+                              gpr_timespec deadline) {
+  return g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline);
 }
 
-void grpc_pollset_kick(grpc_pollset *pollset,
-                       grpc_pollset_worker *specific_worker) {
-  g_event_engine->pollset_kick(pollset, specific_worker);
+grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
+                              grpc_pollset_worker *specific_worker) {
+  return g_event_engine->pollset_kick(pollset, specific_worker);
 }
 
 void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -245,6 +249,6 @@
   g_event_engine->pollset_set_del_fd(exec_ctx, pollset_set, fd);
 }
 
-void grpc_kick_poller(void) { g_event_engine->kick_poller(); }
+grpc_error *grpc_kick_poller(void) { return g_event_engine->kick_poller(); }
 
 #endif  // GPR_POSIX_SOCKET
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 344bf63..87e9bc4 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -55,6 +55,7 @@
                             grpc_closure *closure);
   void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                              grpc_closure *closure);
+  bool (*fd_is_shutdown)(grpc_fd *fd);
   grpc_pollset *(*fd_get_read_notifier_pollset)(grpc_exec_ctx *exec_ctx,
                                                 grpc_fd *fd);
 
@@ -63,11 +64,11 @@
                            grpc_closure *closure);
   void (*pollset_reset)(grpc_pollset *pollset);
   void (*pollset_destroy)(grpc_pollset *pollset);
-  void (*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker **worker, gpr_timespec now,
-                       gpr_timespec deadline);
-  void (*pollset_kick)(grpc_pollset *pollset,
-                       grpc_pollset_worker *specific_worker);
+  grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                              grpc_pollset_worker **worker, gpr_timespec now,
+                              gpr_timespec deadline);
+  grpc_error *(*pollset_kick)(grpc_pollset *pollset,
+                              grpc_pollset_worker *specific_worker);
   void (*pollset_add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                          struct grpc_fd *fd);
 
@@ -90,7 +91,7 @@
   void (*pollset_set_del_fd)(grpc_exec_ctx *exec_ctx,
                              grpc_pollset_set *pollset_set, grpc_fd *fd);
 
-  void (*kick_poller)(void);
+  grpc_error *(*kick_poller)(void);
 
   void (*shutdown_engine)(void);
 } grpc_event_engine_vtable;
@@ -116,7 +117,10 @@
 void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
                     int *release_fd, const char *reason);
 
-/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */
+/* Has grpc_fd_shutdown been called on an fd? */
+bool grpc_fd_is_shutdown(grpc_fd *fd);
+
+/* Cause any current and future callbacks to fail. */
 void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
 
 /* Register read interest, causing read_cb to be called once when fd becomes
diff --git a/src/core/lib/iomgr/exec_ctx.c b/src/core/lib/iomgr/exec_ctx.c
index e451479..c44aafc 100644
--- a/src/core/lib/iomgr/exec_ctx.c
+++ b/src/core/lib/iomgr/exec_ctx.c
@@ -63,11 +63,12 @@
     grpc_closure *c = exec_ctx->closure_list.head;
     exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
     while (c != NULL) {
-      bool success = (bool)(c->final_data & 1);
-      grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1);
+      grpc_closure *next = c->next_data.next;
+      grpc_error *error = c->error;
       did_something = true;
       GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
-      c->cb(exec_ctx, c->cb_arg, success);
+      c->cb(exec_ctx, c->cb_arg, error);
+      GRPC_ERROR_UNREF(error);
       GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
       c = next;
     }
@@ -81,11 +82,11 @@
   grpc_exec_ctx_flush(exec_ctx);
 }
 
-void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                           bool success,
-                           grpc_workqueue *offload_target_or_null) {
+void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                         grpc_error *error,
+                         grpc_workqueue *offload_target_or_null) {
   GPR_ASSERT(offload_target_or_null == NULL);
-  grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
+  grpc_closure_list_append(&exec_ctx->closure_list, closure, error);
 }
 
 void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index 9d47a26..38f27d9 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -94,9 +94,9 @@
  *  the instance is destroyed, or work may be lost. */
 void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
 /** Add a closure to be executed at the next flush/finish point */
-void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
-                           bool success,
-                           grpc_workqueue *offload_target_or_null);
+void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                         grpc_error *error,
+                         grpc_workqueue *offload_target_or_null);
 /** Returns true if we'd like to leave this execution context as soon as
     possible: useful for deciding whether to do something more or not depending
     on outside context */
diff --git a/src/core/lib/iomgr/executor.c b/src/core/lib/iomgr/executor.c
index 36e22e4..8d7535d 100644
--- a/src/core/lib/iomgr/executor.c
+++ b/src/core/lib/iomgr/executor.c
@@ -112,10 +112,10 @@
   g_executor.pending_join = 1;
 }
 
-void grpc_executor_enqueue(grpc_closure *closure, bool success) {
+void grpc_executor_push(grpc_closure *closure, grpc_error *error) {
   gpr_mu_lock(&g_executor.mu);
   if (g_executor.shutting_down == 0) {
-    grpc_closure_list_add(&g_executor.closures, closure, success);
+    grpc_closure_list_append(&g_executor.closures, closure, error);
     maybe_spawn_locked();
   }
   gpr_mu_unlock(&g_executor.mu);
diff --git a/src/core/lib/iomgr/executor.h b/src/core/lib/iomgr/executor.h
index b7e6f51..da9dcd0 100644
--- a/src/core/lib/iomgr/executor.h
+++ b/src/core/lib/iomgr/executor.h
@@ -45,7 +45,7 @@
 
 /** Enqueue \a closure for its eventual execution of \a f(arg) on a separate
  * thread */
-void grpc_executor_enqueue(grpc_closure *closure, bool success);
+void grpc_executor_push(grpc_closure *closure, grpc_error *error);
 
 /** Shutdown the executor, running all pending work as part of the call */
 void grpc_executor_shutdown();
diff --git a/src/core/lib/iomgr/iocp_windows.c b/src/core/lib/iomgr/iocp_windows.c
index 7082322..2532e52 100644
--- a/src/core/lib/iomgr/iocp_windows.c
+++ b/src/core/lib/iomgr/iocp_windows.c
@@ -104,7 +104,6 @@
   } else if (overlapped == &socket->read_info.overlapped) {
     info = &socket->read_info;
   } else {
-    gpr_log(GPR_ERROR, "Unknown IOCP operation");
     abort();
   }
   success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
@@ -112,16 +111,7 @@
   info->bytes_transfered = bytes;
   info->wsa_error = success ? 0 : WSAGetLastError();
   GPR_ASSERT(overlapped == &info->overlapped);
-  GPR_ASSERT(!info->has_pending_iocp);
-  gpr_mu_lock(&socket->state_mu);
-  if (info->closure) {
-    closure = info->closure;
-    info->closure = NULL;
-  } else {
-    info->has_pending_iocp = 1;
-  }
-  gpr_mu_unlock(&socket->state_mu);
-  grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+  grpc_socket_become_ready(exec_ctx, socket, info);
   return GRPC_IOCP_WORK_WORK;
 }
 
@@ -176,33 +166,4 @@
   GPR_ASSERT(ret == g_iocp);
 }
 
-/* Calling notify_on_read or write means either of two things:
-   -) The IOCP already completed in the background, and we need to call
-   the callback now.
-   -) The IOCP hasn't completed yet, and we're queuing it for later. */
-static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
-                                  grpc_winsocket *socket, grpc_closure *closure,
-                                  grpc_winsocket_callback_info *info) {
-  GPR_ASSERT(info->closure == NULL);
-  gpr_mu_lock(&socket->state_mu);
-  if (info->has_pending_iocp) {
-    info->has_pending_iocp = 0;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
-  } else {
-    info->closure = closure;
-  }
-  gpr_mu_unlock(&socket->state_mu);
-}
-
-void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
-                                 grpc_winsocket *socket,
-                                 grpc_closure *closure) {
-  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
-}
-
-void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
-                                grpc_closure *closure) {
-  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
-}
-
 #endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/iocp_windows.h b/src/core/lib/iomgr/iocp_windows.h
index ae210fa..011fee3 100644
--- a/src/core/lib/iomgr/iocp_windows.h
+++ b/src/core/lib/iomgr/iocp_windows.h
@@ -52,12 +52,4 @@
 void grpc_iocp_shutdown(void);
 void grpc_iocp_add_socket(grpc_winsocket *);
 
-void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
-                                 grpc_winsocket *winsocket,
-                                 grpc_closure *closure);
-
-void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
-                                grpc_winsocket *winsocket,
-                                grpc_closure *closure);
-
 #endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */
diff --git a/src/core/lib/support/load_file.c b/src/core/lib/iomgr/load_file.c
similarity index 79%
rename from src/core/lib/support/load_file.c
rename to src/core/lib/iomgr/load_file.c
index f30aacd..b62ecbc 100644
--- a/src/core/lib/support/load_file.c
+++ b/src/core/lib/iomgr/load_file.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/iomgr/load_file.h"
 
 #include <errno.h>
 #include <string.h>
@@ -43,21 +43,19 @@
 #include "src/core/lib/support/block_annotate.h"
 #include "src/core/lib/support/string.h"
 
-gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
-                        int *success) {
+grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
+                           gpr_slice *output) {
   unsigned char *contents = NULL;
   size_t contents_size = 0;
-  char *error_msg = NULL;
   gpr_slice result = gpr_empty_slice();
   FILE *file;
   size_t bytes_read = 0;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   GRPC_SCHEDULING_START_BLOCKING_REGION;
   file = fopen(filename, "rb");
   if (file == NULL) {
-    gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
-                 strerror(errno));
-    GPR_ASSERT(error_msg != NULL);
+    error = GRPC_OS_ERROR(errno, "fopen");
     goto end;
   }
   fseek(file, 0, SEEK_END);
@@ -67,25 +65,25 @@
   contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
   bytes_read = fread(contents, 1, contents_size, file);
   if (bytes_read < contents_size) {
+    error = GRPC_OS_ERROR(errno, "fread");
     GPR_ASSERT(ferror(file));
-    gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
-                 strerror(errno), filename);
-    GPR_ASSERT(error_msg != NULL);
     goto end;
   }
-  if (success != NULL) *success = 1;
   if (add_null_terminator) {
     contents[contents_size++] = 0;
   }
   result = gpr_slice_new(contents, contents_size, gpr_free);
 
 end:
-  if (error_msg != NULL) {
-    gpr_log(GPR_ERROR, "%s", error_msg);
-    gpr_free(error_msg);
-    if (success != NULL) *success = 0;
-  }
+  *output = result;
   if (file != NULL) fclose(file);
+  if (error != GRPC_ERROR_NONE) {
+    grpc_error *error_out = grpc_error_set_str(
+        GRPC_ERROR_CREATE_REFERENCING("Failed to load file", &error, 1),
+        GRPC_ERROR_STR_FILENAME, filename);
+    GRPC_ERROR_UNREF(error);
+    error = error_out;
+  }
   GRPC_SCHEDULING_END_BLOCKING_REGION;
-  return result;
+  return error;
 }
diff --git a/src/core/lib/support/load_file.h b/src/core/lib/iomgr/load_file.h
similarity index 82%
rename from src/core/lib/support/load_file.h
rename to src/core/lib/iomgr/load_file.h
index 9a4b279..9aac222 100644
--- a/src/core/lib/support/load_file.h
+++ b/src/core/lib/iomgr/load_file.h
@@ -31,25 +31,26 @@
  *
  */
 
-#ifndef GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H
-#define GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H
+#ifndef GRPC_CORE_LIB_IOMGR_LOAD_FILE_H
+#define GRPC_CORE_LIB_IOMGR_LOAD_FILE_H
 
 #include <stdio.h>
 
 #include <grpc/support/slice.h>
 
+#include "src/core/lib/iomgr/error.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* Loads the content of a file into a slice. add_null_terminator will add
-   a NULL terminator if non-zero. The success parameter, if not NULL,
-   will be set to 1 in case of success and 0 in case of failure. */
-gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
-                        int *success);
+   a NULL terminator if non-zero. */
+grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
+                           gpr_slice *slice);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H */
+#endif /* GRPC_CORE_LIB_IOMGR_LOAD_FILE_H */
diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h
index c40a474..8d9edc8 100644
--- a/src/core/lib/iomgr/pollset.h
+++ b/src/core/lib/iomgr/pollset.h
@@ -81,14 +81,15 @@
    May call grpc_closure_list_run on grpc_closure_list, without holding the
    pollset
    lock */
-void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker **worker, gpr_timespec now,
-                       gpr_timespec deadline);
+grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                              grpc_pollset_worker **worker, gpr_timespec now,
+                              gpr_timespec deadline) GRPC_MUST_USE_RESULT;
 
 /* Break one polling thread out of polling work for this pollset.
    If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.
    Otherwise, if specific_worker is non-NULL, then kick that worker. */
-void grpc_pollset_kick(grpc_pollset *pollset,
-                       grpc_pollset_worker *specific_worker);
+grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
+                              grpc_pollset_worker *specific_worker)
+    GRPC_MUST_USE_RESULT;
 
 #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_H */
diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c
index bff5c58..626dd78 100644
--- a/src/core/lib/iomgr/pollset_windows.c
+++ b/src/core/lib/iomgr/pollset_windows.c
@@ -109,7 +109,7 @@
   pollset->shutting_down = 1;
   grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
   if (!pollset->is_iocp_worker) {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
   } else {
     pollset->on_shutdown = closure;
   }
@@ -127,9 +127,9 @@
   pollset->on_shutdown = NULL;
 }
 
-void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker **worker_hdl, gpr_timespec now,
-                       gpr_timespec deadline) {
+grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
+                              grpc_pollset_worker **worker_hdl,
+                              gpr_timespec now, gpr_timespec deadline) {
   grpc_pollset_worker worker;
   *worker_hdl = &worker;
 
@@ -167,7 +167,8 @@
       }
 
       if (pollset->shutting_down && pollset->on_shutdown != NULL) {
-        grpc_exec_ctx_enqueue(exec_ctx, pollset->on_shutdown, true, NULL);
+        grpc_exec_ctx_sched(exec_ctx, pollset->on_shutdown, GRPC_ERROR_NONE,
+                            NULL);
         pollset->on_shutdown = NULL;
       }
       goto done;
@@ -197,9 +198,11 @@
   }
   gpr_cv_destroy(&worker.cv);
   *worker_hdl = NULL;
+  return GRPC_ERROR_NONE;
 }
 
-void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
+grpc_error *grpc_pollset_kick(grpc_pollset *p,
+                              grpc_pollset_worker *specific_worker) {
   if (specific_worker != NULL) {
     if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
       for (specific_worker =
@@ -233,6 +236,7 @@
       p->kicked_without_pollers = 1;
     }
   }
+  return GRPC_ERROR_NONE;
 }
 
 void grpc_kick_poller(void) { grpc_iocp_kick(); }
diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h
index ef198fe..ddbe375 100644
--- a/src/core/lib/iomgr/resolve_address.h
+++ b/src/core/lib/iomgr/resolve_address.h
@@ -50,24 +50,20 @@
   grpc_resolved_address *addrs;
 } grpc_resolved_addresses;
 
-/* Async result callback:
-   On success: addresses is the result, and the callee must call
-   grpc_resolved_addresses_destroy when it's done with them
-   On failure: addresses is NULL */
-typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
-                                grpc_resolved_addresses *addresses);
 /* Asynchronously resolve addr. Use default_port if a port isn't designated
    in addr, otherwise use the port in addr. */
 /* TODO(ctiller): add a timeout here */
 extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
                                     const char *default_port,
-                                    grpc_resolve_cb cb, void *arg);
+                                    grpc_closure *on_done,
+                                    grpc_resolved_addresses **addresses);
 /* Destroy resolved addresses */
 void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
 
 /* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
    result must be freed with grpc_resolved_addresses_destroy. */
-extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port);
+extern grpc_error *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port,
+    grpc_resolved_addresses **addresses);
 
 #endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */
diff --git a/src/core/lib/iomgr/resolve_address_posix.c b/src/core/lib/iomgr/resolve_address_posix.c
index cae91ee..4e9f978 100644
--- a/src/core/lib/iomgr/resolve_address_posix.c
+++ b/src/core/lib/iomgr/resolve_address_posix.c
@@ -54,38 +54,33 @@
 #include "src/core/lib/support/block_annotate.h"
 #include "src/core/lib/support/string.h"
 
-typedef struct {
-  char *name;
-  char *default_port;
-  grpc_resolve_cb cb;
-  grpc_closure request_closure;
-  void *arg;
-} request;
-
-static grpc_resolved_addresses *blocking_resolve_address_impl(
-    const char *name, const char *default_port) {
+static grpc_error *blocking_resolve_address_impl(
+    const char *name, const char *default_port,
+    grpc_resolved_addresses **addresses) {
   struct addrinfo hints;
   struct addrinfo *result = NULL, *resp;
   char *host;
   char *port;
   int s;
   size_t i;
-  grpc_resolved_addresses *addrs = NULL;
+  grpc_error *err;
 
   if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
       name[4] == ':' && name[5] != 0) {
-    return grpc_resolve_unix_domain_address(name + 5);
+    return grpc_resolve_unix_domain_address(name + 5, addresses);
   }
 
   /* parse name, splitting it into host and port parts */
   gpr_split_host_port(name, &host, &port);
   if (host == NULL) {
-    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
+    err = grpc_error_set_str(GRPC_ERROR_CREATE("unparseable host:port"),
+                             GRPC_ERROR_STR_TARGET_ADDRESS, name);
     goto done;
   }
   if (port == NULL) {
     if (default_port == NULL) {
-      gpr_log(GPR_ERROR, "no port in name '%s'", name);
+      err = grpc_error_set_str(GRPC_ERROR_CREATE("no port in name"),
+                               GRPC_ERROR_STR_TARGET_ADDRESS, name);
       goto done;
     }
     port = gpr_strdup(default_port);
@@ -115,23 +110,31 @@
   }
 
   if (s != 0) {
-    gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
+    err = grpc_error_set_str(
+        grpc_error_set_str(
+            grpc_error_set_str(grpc_error_set_int(GRPC_ERROR_CREATE("OS Error"),
+                                                  GRPC_ERROR_INT_ERRNO, s),
+                               GRPC_ERROR_STR_OS_ERROR, gai_strerror(s)),
+            GRPC_ERROR_STR_SYSCALL, "getaddrinfo"),
+        GRPC_ERROR_STR_TARGET_ADDRESS, name);
     goto done;
   }
 
   /* Success path: set addrs non-NULL, fill it in */
-  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  addrs->naddrs = 0;
+  *addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
+  (*addresses)->naddrs = 0;
   for (resp = result; resp != NULL; resp = resp->ai_next) {
-    addrs->naddrs++;
+    (*addresses)->naddrs++;
   }
-  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
+  (*addresses)->addrs =
+      gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
   i = 0;
   for (resp = result; resp != NULL; resp = resp->ai_next) {
-    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
-    addrs->addrs[i].len = resp->ai_addrlen;
+    memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
+    (*addresses)->addrs[i].len = resp->ai_addrlen;
     i++;
   }
+  err = GRPC_ERROR_NONE;
 
 done:
   gpr_free(host);
@@ -139,45 +142,59 @@
   if (result) {
     freeaddrinfo(result);
   }
-  return addrs;
+  return err;
 }
 
-grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port) = blocking_resolve_address_impl;
+grpc_error *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port,
+    grpc_resolved_addresses **addresses) = blocking_resolve_address_impl;
+
+typedef struct {
+  char *name;
+  char *default_port;
+  grpc_closure *on_done;
+  grpc_resolved_addresses **addrs_out;
+  grpc_closure request_closure;
+  void *arg;
+} request;
 
 /* Callback to be passed to grpc_executor to asynch-ify
  * grpc_blocking_resolve_address */
-static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
+static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp,
+                              grpc_error *error) {
   request *r = rp;
-  grpc_resolved_addresses *resolved =
-      grpc_blocking_resolve_address(r->name, r->default_port);
-  void *arg = r->arg;
-  grpc_resolve_cb cb = r->cb;
+  grpc_exec_ctx_sched(
+      exec_ctx, r->on_done,
+      grpc_blocking_resolve_address(r->name, r->default_port, r->addrs_out),
+      NULL);
   gpr_free(r->name);
   gpr_free(r->default_port);
-  cb(exec_ctx, arg, resolved);
   gpr_free(r);
 }
 
 void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
-  gpr_free(addrs->addrs);
+  if (addrs != NULL) {
+    gpr_free(addrs->addrs);
+  }
   gpr_free(addrs);
 }
 
 static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
-                                 const char *default_port, grpc_resolve_cb cb,
-                                 void *arg) {
+                                 const char *default_port,
+                                 grpc_closure *on_done,
+                                 grpc_resolved_addresses **addrs) {
   request *r = gpr_malloc(sizeof(request));
   grpc_closure_init(&r->request_closure, do_request_thread, r);
   r->name = gpr_strdup(name);
   r->default_port = gpr_strdup(default_port);
-  r->cb = cb;
-  r->arg = arg;
-  grpc_executor_enqueue(&r->request_closure, 1);
+  r->on_done = on_done;
+  r->addrs_out = addrs;
+  grpc_executor_push(&r->request_closure, GRPC_ERROR_NONE);
 }
 
 void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
-                             const char *default_port, grpc_resolve_cb cb,
-                             void *arg) = resolve_address_impl;
+                             const char *default_port, grpc_closure *on_done,
+                             grpc_resolved_addresses **addrs) =
+    resolve_address_impl;
 
 #endif
diff --git a/src/core/lib/iomgr/resolve_address_windows.c b/src/core/lib/iomgr/resolve_address_windows.c
index c1bbb3d..2af8af8 100644
--- a/src/core/lib/iomgr/resolve_address_windows.c
+++ b/src/core/lib/iomgr/resolve_address_windows.c
@@ -56,30 +56,37 @@
 typedef struct {
   char *name;
   char *default_port;
-  grpc_resolve_cb cb;
   grpc_closure request_closure;
-  void *arg;
+  grpc_closure *on_done;
+  grpc_resolved_addresses **addresses;
 } request;
 
-static grpc_resolved_addresses *blocking_resolve_address_impl(
-    const char *name, const char *default_port) {
+static grpc_error *blocking_resolve_address_impl(
+    const char *name, const char *default_port,
+    grpc_resolved_addresses **addresses) {
   struct addrinfo hints;
   struct addrinfo *result = NULL, *resp;
   char *host;
   char *port;
   int s;
   size_t i;
-  grpc_resolved_addresses *addrs = NULL;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* parse name, splitting it into host and port parts */
   gpr_split_host_port(name, &host, &port);
   if (host == NULL) {
-    gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
+    char *msg;
+    gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
+    error = GRPC_ERROR_CREATE(msg);
+    gpr_free(msg);
     goto done;
   }
   if (port == NULL) {
     if (default_port == NULL) {
-      gpr_log(GPR_ERROR, "no port in name '%s'", name);
+      char *msg;
+      gpr_asprintf(&msg, "no port in name '%s'", name);
+      error = GRPC_ERROR_CREATE(msg);
+      gpr_free(msg);
       goto done;
     }
     port = gpr_strdup(default_port);
@@ -95,31 +102,30 @@
   s = getaddrinfo(host, port, &hints, &result);
   GRPC_SCHEDULING_END_BLOCKING_REGION;
   if (s != 0) {
-    char *error_message = gpr_format_message(s);
-    gpr_log(GPR_ERROR, "getaddrinfo: %s", error_message);
-    gpr_free(error_message);
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "getaddrinfo");
     goto done;
   }
 
   /* Success path: set addrs non-NULL, fill it in */
-  addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  addrs->naddrs = 0;
+  (*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses));
+  (*addresses)->naddrs = 0;
   for (resp = result; resp != NULL; resp = resp->ai_next) {
-    addrs->naddrs++;
+    (*addresses)->naddrs++;
   }
-  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
+  (*addresses)->addrs =
+      gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
   i = 0;
   for (resp = result; resp != NULL; resp = resp->ai_next) {
-    memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
-    addrs->addrs[i].len = resp->ai_addrlen;
+    memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
+    (*addresses)->addrs[i].len = resp->ai_addrlen;
     i++;
   }
 
   {
-    for (i = 0; i < addrs->naddrs; i++) {
+    for (i = 0; i < (*addresses)->naddrs; i++) {
       char *buf;
-      grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
-                              0);
+      grpc_sockaddr_to_string(
+          &buf, (struct sockaddr *)&(*addresses)->addrs[i].addr, 0);
       gpr_free(buf);
     }
   }
@@ -130,45 +136,53 @@
   if (result) {
     freeaddrinfo(result);
   }
-  return addrs;
+  return error;
 }
 
-grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
-    const char *name, const char *default_port) = blocking_resolve_address_impl;
+grpc_error *(*grpc_blocking_resolve_address)(
+    const char *name, const char *default_port,
+    grpc_resolved_addresses **addresses) = blocking_resolve_address_impl;
 
 /* Callback to be passed to grpc_executor to asynch-ify
  * grpc_blocking_resolve_address */
-static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
+static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp,
+                              grpc_error *error) {
   request *r = rp;
-  grpc_resolved_addresses *resolved =
-      grpc_blocking_resolve_address(r->name, r->default_port);
-  void *arg = r->arg;
-  grpc_resolve_cb cb = r->cb;
+  if (error == GRPC_ERROR_NONE) {
+    error =
+        grpc_blocking_resolve_address(r->name, r->default_port, r->addresses);
+  } else {
+    GRPC_ERROR_REF(error);
+  }
+  grpc_exec_ctx_sched(exec_ctx, r->on_done, error, NULL);
   gpr_free(r->name);
   gpr_free(r->default_port);
-  cb(exec_ctx, arg, resolved);
   gpr_free(r);
 }
 
 void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
-  gpr_free(addrs->addrs);
+  if (addrs != NULL) {
+    gpr_free(addrs->addrs);
+  }
   gpr_free(addrs);
 }
 
 static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
-                                 const char *default_port, grpc_resolve_cb cb,
-                                 void *arg) {
+                                 const char *default_port,
+                                 grpc_closure *on_done,
+                                 grpc_resolved_addresses **addresses) {
   request *r = gpr_malloc(sizeof(request));
   grpc_closure_init(&r->request_closure, do_request_thread, r);
   r->name = gpr_strdup(name);
   r->default_port = gpr_strdup(default_port);
-  r->cb = cb;
-  r->arg = arg;
-  grpc_executor_enqueue(&r->request_closure, 1);
+  r->on_done = on_done;
+  r->addresses = addresses;
+  grpc_executor_push(&r->request_closure, GRPC_ERROR_NONE);
 }
 
 void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
-                             const char *default_port, grpc_resolve_cb cb,
-                             void *arg) = resolve_address_impl;
+                             const char *default_port, grpc_closure *on_done,
+                             grpc_resolved_addresses **addresses) =
+    resolve_address_impl;
 
 #endif
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.c b/src/core/lib/iomgr/socket_utils_common_posix.c
index 2147c86..3a13716 100644
--- a/src/core/lib/iomgr/socket_utils_common_posix.c
+++ b/src/core/lib/iomgr/socket_utils_common_posix.c
@@ -49,6 +49,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
@@ -57,10 +58,10 @@
 #include "src/core/lib/support/string.h"
 
 /* set a socket to non blocking mode */
-int grpc_set_socket_nonblocking(int fd, int non_blocking) {
+grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking) {
   int oldflags = fcntl(fd, F_GETFL, 0);
   if (oldflags < 0) {
-    return 0;
+    return GRPC_OS_ERROR(errno, "fcntl");
   }
 
   if (non_blocking) {
@@ -70,62 +71,71 @@
   }
 
   if (fcntl(fd, F_SETFL, oldflags) != 0) {
-    return 0;
+    return GRPC_OS_ERROR(errno, "fcntl");
   }
 
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_set_socket_no_sigpipe_if_possible(int fd) {
+grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd) {
 #ifdef GPR_HAVE_SO_NOSIGPIPE
   int val = 1;
   int newval;
   socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)) &&
-         0 == getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen) &&
-         (newval != 0) == val;
-#else
-  return 1;
+  if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val))) {
+    return GRPC_OS_ERROR(errno, "setsockopt(SO_NOSIGPIPE)");
+  }
+  if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) {
+    return GRPC_OS_ERROR(errno, "getsockopt(SO_NOSIGPIPE)");
+  }
+  if ((newval != 0) != (val != 0)) {
+    return GRPC_ERROR_CREATE("Failed to set SO_NOSIGPIPE");
+  }
 #endif
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_set_socket_ip_pktinfo_if_possible(int fd) {
+grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd) {
 #ifdef GPR_HAVE_IP_PKTINFO
   int get_local_ip = 1;
-  return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
-                         sizeof(get_local_ip));
-#else
-  (void)fd;
-  return 1;
+  if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
+                      sizeof(get_local_ip))) {
+    return GRPC_OS_ERROR(errno, "setsockopt(IP_PKTINFO)");
+  }
 #endif
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
+grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
 #ifdef GPR_HAVE_IPV6_RECVPKTINFO
   int get_local_ip = 1;
-  return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
-                         sizeof(get_local_ip));
-#else
-  (void)fd;
-  return 1;
+  if (0 != setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
+                      sizeof(get_local_ip))) {
+    return GRPC_OS_ERROR(errno, "setsockopt(IPV6_RECVPKTINFO)");
+  }
 #endif
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
+grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
   return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes,
-                         sizeof(buffer_size_bytes));
+                         sizeof(buffer_size_bytes))
+             ? GRPC_ERROR_NONE
+             : GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)");
 }
 
-int grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
+grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
   return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes,
-                         sizeof(buffer_size_bytes));
+                         sizeof(buffer_size_bytes))
+             ? GRPC_ERROR_NONE
+             : GRPC_OS_ERROR(errno, "setsockopt(SO_RCVBUF)");
 }
 
 /* set a socket to close on exec */
-int grpc_set_socket_cloexec(int fd, int close_on_exec) {
+grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec) {
   int oldflags = fcntl(fd, F_GETFD, 0);
   if (oldflags < 0) {
-    return 0;
+    return GRPC_OS_ERROR(errno, "fcntl");
   }
 
   if (close_on_exec) {
@@ -135,30 +145,45 @@
   }
 
   if (fcntl(fd, F_SETFD, oldflags) != 0) {
-    return 0;
+    return GRPC_OS_ERROR(errno, "fcntl");
   }
 
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
 /* set a socket to reuse old addresses */
-int grpc_set_socket_reuse_addr(int fd, int reuse) {
+grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse) {
   int val = (reuse != 0);
   int newval;
   socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) &&
-         0 == getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen) &&
-         (newval != 0) == val;
+  if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
+    return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEADDR)");
+  }
+  if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
+    return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEADDR)");
+  }
+  if ((newval != 0) != val) {
+    return GRPC_ERROR_CREATE("Failed to set SO_REUSEADDR");
+  }
+
+  return GRPC_ERROR_NONE;
 }
 
 /* disable nagle */
-int grpc_set_socket_low_latency(int fd, int low_latency) {
+grpc_error *grpc_set_socket_low_latency(int fd, int low_latency) {
   int val = (low_latency != 0);
   int newval;
   socklen_t intlen = sizeof(newval);
-  return 0 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) &&
-         0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen) &&
-         (newval != 0) == val;
+  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) {
+    return GRPC_OS_ERROR(errno, "setsockopt(TCP_NODELAY)");
+  }
+  if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) {
+    return GRPC_OS_ERROR(errno, "getsockopt(TCP_NODELAY)");
+  }
+  if ((newval != 0) != val) {
+    return GRPC_ERROR_CREATE("Failed to set TCP_NODELAY");
+  }
+  return GRPC_ERROR_NONE;
 }
 
 static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
@@ -206,35 +231,47 @@
   }
 }
 
-int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
-                                 int protocol, grpc_dualstack_mode *dsmode) {
+static grpc_error *error_for_fd(int fd, const struct sockaddr *addr) {
+  if (fd >= 0) return GRPC_ERROR_NONE;
+  char *addr_str;
+  grpc_sockaddr_to_string(&addr_str, addr, 0);
+  grpc_error *err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"),
+                                       GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
+  gpr_free(addr_str);
+  return err;
+}
+
+grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+                                         int protocol,
+                                         grpc_dualstack_mode *dsmode,
+                                         int *newfd) {
   int family = addr->sa_family;
   if (family == AF_INET6) {
-    int fd;
     if (grpc_ipv6_loopback_available()) {
-      fd = socket(family, type, protocol);
+      *newfd = socket(family, type, protocol);
     } else {
-      fd = -1;
+      *newfd = -1;
       errno = EAFNOSUPPORT;
     }
     /* Check if we've got a valid dualstack socket. */
-    if (fd >= 0 && set_socket_dualstack(fd)) {
+    if (*newfd >= 0 && set_socket_dualstack(*newfd)) {
       *dsmode = GRPC_DSMODE_DUALSTACK;
-      return fd;
+      return GRPC_ERROR_NONE;
     }
     /* If this isn't an IPv4 address, then return whatever we've got. */
     if (!grpc_sockaddr_is_v4mapped(addr, NULL)) {
       *dsmode = GRPC_DSMODE_IPV6;
-      return fd;
+      return error_for_fd(*newfd, addr);
     }
     /* Fall back to AF_INET. */
-    if (fd >= 0) {
-      close(fd);
+    if (*newfd >= 0) {
+      close(*newfd);
     }
     family = AF_INET;
   }
   *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
-  return socket(family, type, protocol);
+  *newfd = socket(family, type, protocol);
+  return error_for_fd(*newfd, addr);
 }
 
 #endif
diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h
index 7e41d1c..30ff39d 100644
--- a/src/core/lib/iomgr/socket_utils_posix.h
+++ b/src/core/lib/iomgr/socket_utils_posix.h
@@ -37,21 +37,23 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include "src/core/lib/iomgr/error.h"
+
 /* a wrapper for accept or accept4 */
 int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
                  int nonblock, int cloexec);
 
 /* set a socket to non blocking mode */
-int grpc_set_socket_nonblocking(int fd, int non_blocking);
+grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking);
 
 /* set a socket to close on exec */
-int grpc_set_socket_cloexec(int fd, int close_on_exec);
+grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec);
 
 /* set a socket to reuse old addresses */
-int grpc_set_socket_reuse_addr(int fd, int reuse);
+grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse);
 
 /* disable nagle */
-int grpc_set_socket_low_latency(int fd, int low_latency);
+grpc_error *grpc_set_socket_low_latency(int fd, int low_latency);
 
 /* Returns true if this system can create AF_INET6 sockets bound to ::1.
    The value is probed once, and cached for the life of the process.
@@ -64,27 +66,22 @@
 int grpc_ipv6_loopback_available(void);
 
 /* Tries to set SO_NOSIGPIPE if available on this platform.
-   Returns 1 on success, 0 on failure.
    If SO_NO_SIGPIPE is not available, returns 1. */
-int grpc_set_socket_no_sigpipe_if_possible(int fd);
+grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd);
 
 /* Tries to set IP_PKTINFO if available on this platform.
-   Returns 1 on success, 0 on failure.
    If IP_PKTINFO is not available, returns 1. */
-int grpc_set_socket_ip_pktinfo_if_possible(int fd);
+grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd);
 
 /* Tries to set IPV6_RECVPKTINFO if available on this platform.
-   Returns 1 on success, 0 on failure.
    If IPV6_RECVPKTINFO is not available, returns 1. */
-int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd);
+grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd);
 
-/* Tries to set the socket's send buffer to given size.
-   Returns 1 on success, 0 on failure. */
-int grpc_set_socket_sndbuf(int fd, int buffer_size_bytes);
+/* Tries to set the socket's send buffer to given size. */
+grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes);
 
-/* Tries to set the socket's receive buffer to given size.
-   Returns 1 on success, 0 on failure. */
-int grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes);
+/* Tries to set the socket's receive buffer to given size. */
+grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes);
 
 /* An enum to keep track of IPv4/IPv6 socket modes.
 
@@ -125,7 +122,9 @@
      IPv4, so that bind() or connect() see the correct family.
    Also, it's important to distinguish between DUALSTACK and IPV6 when
    listening on the [::] wildcard address. */
-int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
-                                 int protocol, grpc_dualstack_mode *dsmode);
+grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
+                                         int protocol,
+                                         grpc_dualstack_mode *dsmode,
+                                         int *newfd);
 
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */
diff --git a/src/core/lib/iomgr/socket_windows.c b/src/core/lib/iomgr/socket_windows.c
index 7d8f9f7..d7d5f6f 100644
--- a/src/core/lib/iomgr/socket_windows.c
+++ b/src/core/lib/iomgr/socket_windows.c
@@ -91,10 +91,69 @@
   closesocket(winsocket->socket);
 }
 
-void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
+static void destroy(grpc_winsocket *winsocket) {
   grpc_iomgr_unregister_object(&winsocket->iomgr_object);
   gpr_mu_destroy(&winsocket->state_mu);
   gpr_free(winsocket);
 }
 
+static bool check_destroyable(grpc_winsocket *winsocket) {
+  return winsocket->destroy_called == true &&
+         winsocket->write_info.closure == NULL &&
+         winsocket->read_info.closure == NULL;
+}
+
+void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
+  gpr_mu_lock(&winsocket->state_mu);
+  GPR_ASSERT(!winsocket->destroy_called);
+  winsocket->destroy_called = true;
+  bool should_destroy = check_destroyable(winsocket);
+  gpr_mu_unlock(&winsocket->state_mu);
+  if (should_destroy) destroy(winsocket);
+}
+
+/* Calling notify_on_read or write means either of two things:
+-) The IOCP already completed in the background, and we need to call
+the callback now.
+-) The IOCP hasn't completed yet, and we're queuing it for later. */
+static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
+                                  grpc_winsocket *socket, grpc_closure *closure,
+                                  grpc_winsocket_callback_info *info) {
+  GPR_ASSERT(info->closure == NULL);
+  gpr_mu_lock(&socket->state_mu);
+  if (info->has_pending_iocp) {
+    info->has_pending_iocp = 0;
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
+  } else {
+    info->closure = closure;
+  }
+  gpr_mu_unlock(&socket->state_mu);
+}
+
+void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
+                                 grpc_winsocket *socket,
+                                 grpc_closure *closure) {
+  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
+}
+
+void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
+                                grpc_closure *closure) {
+  socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
+}
+
+void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
+                              grpc_winsocket_callback_info *info) {
+  GPR_ASSERT(!info->has_pending_iocp);
+  gpr_mu_lock(&socket->state_mu);
+  if (info->closure) {
+    grpc_exec_ctx_sched(exec_ctx, info->closure, GRPC_ERROR_NONE, NULL);
+    info->closure = NULL;
+  } else {
+    info->has_pending_iocp = 1;
+  }
+  bool should_destroy = check_destroyable(socket);
+  gpr_mu_unlock(&socket->state_mu);
+  if (should_destroy) destroy(socket);
+}
+
 #endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h
index 73c4384..490d0e0 100644
--- a/src/core/lib/iomgr/socket_windows.h
+++ b/src/core/lib/iomgr/socket_windows.h
@@ -81,6 +81,7 @@
    is closer to what happens in posix world. */
 typedef struct grpc_winsocket {
   SOCKET socket;
+  bool destroy_called;
 
   grpc_winsocket_callback_info write_info;
   grpc_winsocket_callback_info read_info;
@@ -108,4 +109,16 @@
 /* Destroy a socket. Should only be called if there's no pending operation. */
 void grpc_winsocket_destroy(grpc_winsocket *socket);
 
+void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
+                                 grpc_winsocket *winsocket,
+                                 grpc_closure *closure);
+
+void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
+                                grpc_winsocket *winsocket,
+                                grpc_closure *closure);
+
+void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx,
+                              grpc_winsocket *winsocket,
+                              grpc_winsocket_callback_info *ci);
+
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
index e93d573..80c7a3f 100644
--- a/src/core/lib/iomgr/tcp_client_posix.c
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -71,33 +71,39 @@
   grpc_closure *closure;
 } async_connect;
 
-static int prepare_socket(const struct sockaddr *addr, int fd) {
-  if (fd < 0) {
-    goto error;
-  }
+static grpc_error *prepare_socket(const struct sockaddr *addr, int fd) {
+  grpc_error *err = GRPC_ERROR_NONE;
 
-  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
-      (!grpc_is_unix_socket(addr) && !grpc_set_socket_low_latency(fd, 1)) ||
-      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
-    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
-            strerror(errno));
-    goto error;
+  GPR_ASSERT(fd >= 0);
+
+  err = grpc_set_socket_nonblocking(fd, 1);
+  if (err != GRPC_ERROR_NONE) goto error;
+  err = grpc_set_socket_cloexec(fd, 1);
+  if (err != GRPC_ERROR_NONE) goto error;
+  if (!grpc_is_unix_socket(addr)) {
+    err = grpc_set_socket_low_latency(fd, 1);
+    if (err != GRPC_ERROR_NONE) goto error;
   }
-  return 1;
+  err = grpc_set_socket_no_sigpipe_if_possible(fd);
+  if (err != GRPC_ERROR_NONE) goto error;
+  goto done;
 
 error:
   if (fd >= 0) {
     close(fd);
   }
-  return 0;
+done:
+  return err;
 }
 
-static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
+static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
   int done;
   async_connect *ac = acp;
   if (grpc_tcp_trace) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
-            success);
+    const char *str = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
+            str);
+    grpc_error_free_string(str);
   }
   gpr_mu_lock(&ac->mu);
   if (ac->fd != NULL) {
@@ -112,7 +118,7 @@
   }
 }
 
-static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
+static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
   async_connect *ac = acp;
   int so_error = 0;
   socklen_t so_error_size;
@@ -122,9 +128,13 @@
   grpc_closure *closure = ac->closure;
   grpc_fd *fd;
 
+  GRPC_ERROR_REF(error);
+
   if (grpc_tcp_trace) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
-            ac->addr_str, success);
+    const char *str = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
+            ac->addr_str, str);
+    grpc_error_free_string(str);
   }
 
   gpr_mu_lock(&ac->mu);
@@ -136,15 +146,14 @@
   grpc_timer_cancel(exec_ctx, &ac->alarm);
 
   gpr_mu_lock(&ac->mu);
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     do {
       so_error_size = sizeof(so_error);
       err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
                        &so_error_size);
     } while (err < 0 && errno == EINTR);
     if (err < 0) {
-      gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
-              ac->addr_str, strerror(errno));
+      error = GRPC_OS_ERROR(errno, "getsockopt");
       goto finish;
     } else if (so_error != 0) {
       if (so_error == ENOBUFS) {
@@ -169,14 +178,12 @@
       } else {
         switch (so_error) {
           case ECONNREFUSED:
-            gpr_log(
-                GPR_ERROR,
-                "failed to connect to '%s': socket error: connection refused",
-                ac->addr_str);
+            error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errno);
+            error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
+                                       "Connection refused");
             break;
           default:
-            gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
-                    ac->addr_str, so_error);
+            error = GRPC_OS_ERROR(errno, "getsockopt(SO_ERROR)");
             break;
         }
         goto finish;
@@ -188,8 +195,8 @@
       goto finish;
     }
   } else {
-    gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
-            ac->addr_str);
+    error =
+        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred");
     goto finish;
   }
 
@@ -203,12 +210,18 @@
   }
   done = (--ac->refs == 0);
   gpr_mu_unlock(&ac->mu);
+  if (error != GRPC_ERROR_NONE) {
+    error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
+                               "Failed to connect to remote host");
+    error =
+        grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
+  }
   if (done) {
     gpr_mu_destroy(&ac->mu);
     gpr_free(ac->addr_str);
     gpr_free(ac);
   }
-  grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
+  grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
 }
 
 static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
@@ -225,6 +238,7 @@
   grpc_fd *fdobj;
   char *name;
   char *addr_str;
+  grpc_error *error;
 
   *ep = NULL;
 
@@ -234,9 +248,10 @@
     addr_len = sizeof(addr6_v4mapped);
   }
 
-  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+  error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
+  if (error != GRPC_ERROR_NONE) {
+    grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
+    return;
   }
   if (dsmode == GRPC_DSMODE_IPV4) {
     /* If we got an AF_INET socket, map the address back to IPv4. */
@@ -244,8 +259,8 @@
     addr = (struct sockaddr *)&addr4_copy;
     addr_len = sizeof(addr4_copy);
   }
-  if (!prepare_socket(addr, fd)) {
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+  if ((error = prepare_socket(addr, fd)) != GRPC_ERROR_NONE) {
+    grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
     return;
   }
 
@@ -261,14 +276,14 @@
 
   if (err >= 0) {
     *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
-    grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
     goto done;
   }
 
   if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
-    gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
     grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect"),
+                        NULL);
     goto done;
   }
 
diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c
index efa0140..562cb9c 100644
--- a/src/core/lib/iomgr/tcp_client_windows.c
+++ b/src/core/lib/iomgr/tcp_client_windows.c
@@ -75,23 +75,25 @@
   if (socket != NULL) grpc_winsocket_destroy(socket);
 }
 
-static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool occured) {
+static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
   async_connect *ac = acp;
   gpr_mu_lock(&ac->mu);
-  if (ac->socket != NULL) {
-    grpc_winsocket_shutdown(ac->socket);
+  grpc_winsocket *socket = ac->socket;
+  ac->socket = NULL;
+  if (socket != NULL) {
+    grpc_winsocket_shutdown(socket);
   }
-  async_connect_unlock_and_cleanup(ac, ac->socket);
+  async_connect_unlock_and_cleanup(ac, socket);
 }
 
-static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, bool from_iocp) {
+static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
   async_connect *ac = acp;
-  SOCKET sock = ac->socket->socket;
   grpc_endpoint **ep = ac->endpoint;
   GPR_ASSERT(*ep == NULL);
-  grpc_winsocket_callback_info *info = &ac->socket->write_info;
   grpc_closure *on_done = ac->on_done;
 
+  GRPC_ERROR_REF(error);
+
   gpr_mu_lock(&ac->mu);
   grpc_winsocket *socket = ac->socket;
   ac->socket = NULL;
@@ -101,17 +103,15 @@
 
   gpr_mu_lock(&ac->mu);
 
-  if (from_iocp && socket != NULL) {
+  if (error == GRPC_ERROR_NONE && socket != NULL) {
     DWORD transfered_bytes = 0;
     DWORD flags;
-    BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
-                                              &transfered_bytes, FALSE, &flags);
+    BOOL wsa_success =
+        WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
+                               &transfered_bytes, FALSE, &flags);
     GPR_ASSERT(transfered_bytes == 0);
     if (!wsa_success) {
-      char *utf8_message = gpr_format_message(WSAGetLastError());
-      gpr_log(GPR_ERROR, "on_connect error connecting to '%s': %s",
-              ac->addr_name, utf8_message);
-      gpr_free(utf8_message);
+      error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
     } else {
       *ep = grpc_tcp_create(socket, ac->addr_name);
       socket = NULL;
@@ -121,7 +121,7 @@
   async_connect_unlock_and_cleanup(ac, socket);
   /* If the connection was aborted, the callback was already called when
      the deadline was met. */
-  on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL);
+  grpc_exec_ctx_sched(exec_ctx, on_done, error, NULL);
 }
 
 /* Tries to issue one async connection, then schedules both an IOCP
@@ -141,10 +141,8 @@
   LPFN_CONNECTEX ConnectEx;
   GUID guid = WSAID_CONNECTEX;
   DWORD ioctl_num_bytes;
-  const char *message = NULL;
-  char *utf8_message;
   grpc_winsocket_callback_info *info;
-  int last_error;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   *endpoint = NULL;
 
@@ -157,12 +155,12 @@
   sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                    WSA_FLAG_OVERLAPPED);
   if (sock == INVALID_SOCKET) {
-    message = "Unable to create socket: %s";
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
     goto failure;
   }
 
-  if (!grpc_tcp_prepare_socket(sock)) {
-    message = "Unable to set socket options: %s";
+  error = grpc_tcp_prepare_socket(sock);
+  if (error != GRPC_ERROR_NONE) {
     goto failure;
   }
 
@@ -173,7 +171,8 @@
                &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL);
 
   if (status != 0) {
-    message = "Unable to retrieve ConnectEx pointer: %s";
+    error = GRPC_WSA_ERROR(WSAGetLastError(),
+                           "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER)");
     goto failure;
   }
 
@@ -181,7 +180,7 @@
 
   status = bind(sock, (struct sockaddr *)&local_address, sizeof(local_address));
   if (status != 0) {
-    message = "Unable to bind socket: %s";
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
     goto failure;
   }
 
@@ -193,9 +192,9 @@
   /* It wouldn't be unusual to get a success immediately. But we'll still get
      an IOCP notification, so let's ignore it. */
   if (!success) {
-    int error = WSAGetLastError();
-    if (error != ERROR_IO_PENDING) {
-      message = "ConnectEx failed: %s";
+    int last_error = WSAGetLastError();
+    if (last_error != ERROR_IO_PENDING) {
+      error = GRPC_WSA_ERROR(last_error, "ConnectEx");
       goto failure;
     }
   }
@@ -215,17 +214,18 @@
   return;
 
 failure:
-  last_error = WSAGetLastError();
-  utf8_message = gpr_format_message(last_error);
-  gpr_log(GPR_ERROR, message, utf8_message);
-  gpr_log(GPR_ERROR, "last error = %d", last_error);
-  gpr_free(utf8_message);
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
+  char *target_uri = grpc_sockaddr_to_uri(addr);
+  grpc_error *final_error = grpc_error_set_str(
+      GRPC_ERROR_CREATE_REFERENCING("Failed to connect", &error, 1),
+      GRPC_ERROR_STR_TARGET_ADDRESS, target_uri);
+  GRPC_ERROR_UNREF(error);
   if (socket != NULL) {
     grpc_winsocket_destroy(socket);
   } else if (sock != INVALID_SOCKET) {
     closesocket(sock);
   }
-  grpc_exec_ctx_enqueue(exec_ctx, on_done, false, NULL);
+  grpc_exec_ctx_sched(exec_ctx, on_done, final_error, NULL);
 }
 
 #endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
index e286922..017f52c 100644
--- a/src/core/lib/iomgr/tcp_posix.c
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -38,6 +38,7 @@
 #include "src/core/lib/iomgr/tcp_posix.h"
 
 #include <errno.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -74,7 +75,7 @@
   grpc_endpoint base;
   grpc_fd *em_fd;
   int fd;
-  int finished_edge;
+  bool finished_edge;
   msg_iovlen_type iov_size; /* Number of slices to allocate per read attempt */
   size_t slice_size;
   gpr_refcount refcount;
@@ -101,9 +102,9 @@
 } grpc_tcp;
 
 static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                            bool success);
+                            grpc_error *error);
 static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                             bool success);
+                             grpc_error *error);
 
 static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
@@ -155,12 +156,15 @@
   TCP_UNREF(exec_ctx, tcp, "destroy");
 }
 
-static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) {
+static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
+                         grpc_error *error) {
   grpc_closure *cb = tcp->read_cb;
 
-  if (grpc_tcp_trace) {
+  if (false && grpc_tcp_trace) {
     size_t i;
-    gpr_log(GPR_DEBUG, "read: success=%d", success);
+    const char *str = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "read: error=%s", str);
+    grpc_error_free_string(str);
     for (i = 0; i < tcp->incoming_buffer->count; i++) {
       char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i],
                                   GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -171,7 +175,7 @@
 
   tcp->read_cb = NULL;
   tcp->incoming_buffer = NULL;
-  cb->cb(exec_ctx, cb->cb_arg, success);
+  grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
 }
 
 #define MAX_READ_IOVEC 4
@@ -219,15 +223,14 @@
       /* We've consumed the edge, request a new one */
       grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
     } else {
-      /* TODO(klempner): Log interesting errors */
       gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-      call_read_cb(exec_ctx, tcp, 0);
+      call_read_cb(exec_ctx, tcp, GRPC_OS_ERROR(errno, "recvmsg"));
       TCP_UNREF(exec_ctx, tcp, "read");
     }
   } else if (read_bytes == 0) {
     /* 0 read size ==> end of stream */
     gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-    call_read_cb(exec_ctx, tcp, 0);
+    call_read_cb(exec_ctx, tcp, GRPC_ERROR_CREATE("EOF"));
     TCP_UNREF(exec_ctx, tcp, "read");
   } else {
     GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
@@ -240,7 +243,7 @@
       ++tcp->iov_size;
     }
     GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
-    call_read_cb(exec_ctx, tcp, 1);
+    call_read_cb(exec_ctx, tcp, GRPC_ERROR_NONE);
     TCP_UNREF(exec_ctx, tcp, "read");
   }
 
@@ -248,13 +251,13 @@
 }
 
 static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                            bool success) {
+                            grpc_error *error) {
   grpc_tcp *tcp = (grpc_tcp *)arg;
   GPR_ASSERT(!tcp->finished_edge);
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
-    call_read_cb(exec_ctx, tcp, 0);
+    call_read_cb(exec_ctx, tcp, GRPC_ERROR_REF(error));
     TCP_UNREF(exec_ctx, tcp, "read");
   } else {
     tcp_continue_read(exec_ctx, tcp);
@@ -271,17 +274,16 @@
   gpr_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer);
   TCP_REF(tcp, "read");
   if (tcp->finished_edge) {
-    tcp->finished_edge = 0;
+    tcp->finished_edge = false;
     grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
   } else {
-    grpc_exec_ctx_enqueue(exec_ctx, &tcp->read_closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &tcp->read_closure, GRPC_ERROR_NONE, NULL);
   }
 }
 
-typedef enum { FLUSH_DONE, FLUSH_PENDING, FLUSH_ERROR } flush_result;
-
+/* returns true if done, false if pending; if returning true, *error is set */
 #define MAX_WRITE_IOVEC 16
-static flush_result tcp_flush(grpc_tcp *tcp) {
+static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) {
   struct msghdr msg;
   struct iovec iov[MAX_WRITE_IOVEC];
   msg_iovlen_type iov_size;
@@ -331,10 +333,10 @@
       if (errno == EAGAIN) {
         tcp->outgoing_slice_idx = unwind_slice_idx;
         tcp->outgoing_byte_idx = unwind_byte_idx;
-        return FLUSH_PENDING;
+        return false;
       } else {
-        /* TODO(klempner): Log some of these */
-        return FLUSH_ERROR;
+        *error = GRPC_OS_ERROR(errno, "sendmsg");
+        return true;
       }
     }
 
@@ -355,44 +357,44 @@
     }
 
     if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) {
-      return FLUSH_DONE;
+      *error = GRPC_ERROR_NONE;
+      return true;
     }
   };
 }
 
 static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
-                             bool success) {
+                             grpc_error *error) {
   grpc_tcp *tcp = (grpc_tcp *)arg;
-  flush_result status;
   grpc_closure *cb;
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     cb = tcp->write_cb;
     tcp->write_cb = NULL;
-    cb->cb(exec_ctx, cb->cb_arg, 0);
+    cb->cb(exec_ctx, cb->cb_arg, error);
     TCP_UNREF(exec_ctx, tcp, "write");
     return;
   }
 
-  status = tcp_flush(tcp);
-  if (status == FLUSH_PENDING) {
+  if (!tcp_flush(tcp, &error)) {
     grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
   } else {
     cb = tcp->write_cb;
     tcp->write_cb = NULL;
     GPR_TIMER_BEGIN("tcp_handle_write.cb", 0);
-    cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE);
+    cb->cb(exec_ctx, cb->cb_arg, error);
     GPR_TIMER_END("tcp_handle_write.cb", 0);
     TCP_UNREF(exec_ctx, tcp, "write");
+    GRPC_ERROR_UNREF(error);
   }
 }
 
 static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                       gpr_slice_buffer *buf, grpc_closure *cb) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
-  flush_result status;
+  grpc_error *error = GRPC_ERROR_NONE;
 
-  if (grpc_tcp_trace) {
+  if (false && grpc_tcp_trace) {
     size_t i;
 
     for (i = 0; i < buf->count; i++) {
@@ -408,20 +410,22 @@
 
   if (buf->length == 0) {
     GPR_TIMER_END("tcp_write", 0);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb, grpc_fd_is_shutdown(tcp->em_fd)
+                                          ? GRPC_ERROR_CREATE("EOF")
+                                          : GRPC_ERROR_NONE,
+                        NULL);
     return;
   }
   tcp->outgoing_buffer = buf;
   tcp->outgoing_slice_idx = 0;
   tcp->outgoing_byte_idx = 0;
 
-  status = tcp_flush(tcp);
-  if (status == FLUSH_PENDING) {
+  if (!tcp_flush(tcp, &error)) {
     TCP_REF(tcp, "write");
     tcp->write_cb = cb;
     grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
   } else {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
   }
 
   GPR_TIMER_END("tcp_write", 0);
@@ -461,7 +465,7 @@
   tcp->incoming_buffer = NULL;
   tcp->slice_size = slice_size;
   tcp->iov_size = 1;
-  tcp->finished_edge = 1;
+  tcp->finished_edge = true;
   /* paired with unref in grpc_tcp_destroy */
   gpr_ref_init(&tcp->refcount, 1);
   tcp->em_fd = em_fd;
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
index fee14ae..1d6e70d 100644
--- a/src/core/lib/iomgr/tcp_server.h
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -58,7 +58,8 @@
 /* Create a server, initially not bound to any ports. The caller owns one ref.
    If shutdown_complete is not NULL, it will be used by
    grpc_tcp_server_unref() when the ref count reaches zero. */
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete);
+grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete,
+                                   grpc_tcp_server **server);
 
 /* Start listening to bound ports */
 void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
@@ -74,8 +75,8 @@
    but not dualstack sockets. */
 /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
                   all of the multiple socket port matching logic in one place */
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len);
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                                     size_t addr_len, int *out_port);
 
 /* Number of fds at the given port_index, or 0 if port_index is out of
    bounds. */
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index 909e34a..6fb547b 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -59,6 +59,8 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/socket_utils_posix.h"
@@ -133,7 +135,8 @@
   size_t next_pollset_to_assign;
 };
 
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
+grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete,
+                                   grpc_tcp_server **server) {
   grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
   gpr_ref_init(&s->refs, 1);
   gpr_mu_init(&s->mu);
@@ -149,12 +152,13 @@
   s->tail = NULL;
   s->nports = 0;
   s->next_pollset_to_assign = 0;
-  return s;
+  *server = s;
+  return GRPC_ERROR_NONE;
 }
 
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
   if (s->shutdown_complete != NULL) {
-    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
   }
 
   gpr_mu_destroy(&s->mu);
@@ -169,7 +173,7 @@
 }
 
 static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
-                           bool success) {
+                           grpc_error *error) {
   grpc_tcp_server *s = server;
   gpr_mu_lock(&s->mu);
   s->destroyed_ports++;
@@ -263,61 +267,68 @@
 }
 
 /* Prepare a recently-created socket for listening. */
-static int prepare_socket(int fd, const struct sockaddr *addr,
-                          size_t addr_len) {
+static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
+                                  size_t addr_len, int *port) {
   struct sockaddr_storage sockname_temp;
   socklen_t sockname_len;
+  grpc_error *err = GRPC_ERROR_NONE;
 
-  if (fd < 0) {
-    goto error;
-  }
+  GPR_ASSERT(fd >= 0);
 
-  if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
-      (!grpc_is_unix_socket(addr) && (!grpc_set_socket_low_latency(fd, 1) ||
-                                      !grpc_set_socket_reuse_addr(fd, 1))) ||
-      !grpc_set_socket_no_sigpipe_if_possible(fd)) {
-    gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
-            strerror(errno));
-    goto error;
+  err = grpc_set_socket_nonblocking(fd, 1);
+  if (err != GRPC_ERROR_NONE) goto error;
+  err = grpc_set_socket_cloexec(fd, 1);
+  if (err != GRPC_ERROR_NONE) goto error;
+  if (!grpc_is_unix_socket(addr)) {
+    err = grpc_set_socket_low_latency(fd, 1);
+    if (err != GRPC_ERROR_NONE) goto error;
+    err = grpc_set_socket_reuse_addr(fd, 1);
+    if (err != GRPC_ERROR_NONE) goto error;
   }
+  err = grpc_set_socket_no_sigpipe_if_possible(fd);
+  if (err != GRPC_ERROR_NONE) goto error;
 
   GPR_ASSERT(addr_len < ~(socklen_t)0);
   if (bind(fd, addr, (socklen_t)addr_len) < 0) {
-    char *addr_str;
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
-    gpr_free(addr_str);
+    err = GRPC_OS_ERROR(errno, "bind");
     goto error;
   }
 
   if (listen(fd, get_max_accept_queue_size()) < 0) {
-    gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
+    err = GRPC_OS_ERROR(errno, "listen");
     goto error;
   }
 
   sockname_len = sizeof(sockname_temp);
   if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
+    err = GRPC_OS_ERROR(errno, "getsockname");
     goto error;
   }
 
-  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  return GRPC_ERROR_NONE;
 
 error:
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
   if (fd >= 0) {
     close(fd);
   }
-  return -1;
+  grpc_error *ret = grpc_error_set_int(
+      GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1),
+      GRPC_ERROR_INT_FD, fd);
+  GRPC_ERROR_UNREF(err);
+  return ret;
 }
 
 /* event manager callback when reads are ready */
-static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
   grpc_tcp_listener *sp = arg;
   grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
                                        sp->fd_index};
   grpc_pollset *read_notifier_pollset = NULL;
   grpc_fd *fdobj;
 
-  if (!success) {
+  if (err != GRPC_ERROR_NONE) {
     goto error;
   }
 
@@ -386,18 +397,19 @@
   }
 }
 
-static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
-                                               const struct sockaddr *addr,
-                                               size_t addr_len,
-                                               unsigned port_index,
-                                               unsigned fd_index) {
+static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
+                                        const struct sockaddr *addr,
+                                        size_t addr_len, unsigned port_index,
+                                        unsigned fd_index,
+                                        grpc_tcp_listener **listener) {
   grpc_tcp_listener *sp = NULL;
-  int port;
+  int port = -1;
   char *addr_str;
   char *name;
 
-  port = prepare_socket(fd, addr, addr_len);
-  if (port >= 0) {
+  grpc_error *err = prepare_socket(fd, addr, addr_len, &port);
+  if (err == GRPC_ERROR_NONE) {
+    GPR_ASSERT(port > 0);
     grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
     gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
     gpr_mu_lock(&s->mu);
@@ -427,11 +439,12 @@
     gpr_free(name);
   }
 
-  return sp;
+  *listener = sp;
+  return err;
 }
 
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                                     size_t addr_len, int *out_port) {
   grpc_tcp_listener *sp;
   grpc_tcp_listener *sp2 = NULL;
   int fd;
@@ -446,6 +459,7 @@
   int port;
   unsigned port_index = 0;
   unsigned fd_index = 0;
+  grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
   if (s->tail != NULL) {
     port_index = s->tail->port_index + 1;
   }
@@ -484,33 +498,35 @@
     /* Try listening on IPv6 first. */
     addr = (struct sockaddr *)&wild6;
     addr_len = sizeof(wild6);
-    fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-    sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
-    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-      goto done;
-    }
-    if (sp != NULL) {
-      ++fd_index;
-    }
-    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && sp != NULL) {
-      grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
+    errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
+    if (errs[0] == GRPC_ERROR_NONE) {
+      errs[0] = add_socket_to_server(s, fd, addr, addr_len, port_index,
+                                     fd_index, &sp);
+      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
+        goto done;
+      }
+      if (sp != NULL) {
+        ++fd_index;
+      }
+      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+      if (port == 0 && sp != NULL) {
+        grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
+      }
     }
     addr = (struct sockaddr *)&wild4;
     addr_len = sizeof(wild4);
   }
 
-  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-  } else {
+  errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
+  if (errs[1] == GRPC_ERROR_NONE) {
     if (dsmode == GRPC_DSMODE_IPV4 &&
         grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
       addr = (struct sockaddr *)&addr4_copy;
       addr_len = sizeof(addr4_copy);
     }
     sp2 = sp;
-    sp = add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index);
+    errs[1] =
+        add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index, &sp);
     if (sp2 != NULL && sp != NULL) {
       sp2->sibling = sp;
       sp->is_sibling = 1;
@@ -520,9 +536,21 @@
 done:
   gpr_free(allocated_addr);
   if (sp != NULL) {
-    return sp->port;
+    *out_port = sp->port;
+    GRPC_ERROR_UNREF(errs[0]);
+    GRPC_ERROR_UNREF(errs[1]);
+    return GRPC_ERROR_NONE;
   } else {
-    return -1;
+    *out_port = -1;
+    char *addr_str = grpc_sockaddr_to_uri(addr);
+    grpc_error *err = grpc_error_set_str(
+        GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
+                                      GPR_ARRAY_SIZE(errs)),
+        GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
+    GRPC_ERROR_UNREF(errs[0]);
+    GRPC_ERROR_UNREF(errs[1]);
+    gpr_free(addr_str);
+    return err;
   }
 }
 
@@ -591,7 +619,8 @@
 void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
                                            grpc_closure *shutdown_starting) {
   gpr_mu_lock(&s->mu);
-  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
+  grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
+                           GRPC_ERROR_NONE);
   gpr_mu_unlock(&s->mu);
 }
 
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 8a21d93..2a51671 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -102,7 +102,8 @@
 
 /* Public function. Allocates the proper data structures to hold a
    grpc_tcp_server. */
-grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
+grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete,
+                                   grpc_tcp_server **server) {
   grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
   gpr_ref_init(&s->refs, 1);
   gpr_mu_init(&s->mu);
@@ -114,12 +115,13 @@
   s->shutdown_starting.head = NULL;
   s->shutdown_starting.tail = NULL;
   s->shutdown_complete = shutdown_complete;
-  return s;
+  *server = s;
+  return GRPC_ERROR_NONE;
 }
 
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
   if (s->shutdown_complete != NULL) {
-    grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
   }
 
   /* Now that the accepts have been aborted, we can destroy the sockets.
@@ -143,7 +145,8 @@
 void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
                                            grpc_closure *shutdown_starting) {
   gpr_mu_lock(&s->mu);
-  grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
+  grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
+                           GRPC_ERROR_NONE);
   gpr_mu_unlock(&s->mu);
 }
 
@@ -187,51 +190,49 @@
 }
 
 /* Prepare (bind) a recently-created socket for listening. */
-static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
-                          size_t addr_len) {
+static grpc_error *prepare_socket(SOCKET sock, const struct sockaddr *addr,
+                                  size_t addr_len, int *port) {
   struct sockaddr_storage sockname_temp;
   socklen_t sockname_len;
+  grpc_error *error = GRPC_ERROR_NONE;
 
-  if (sock == INVALID_SOCKET) goto error;
-
-  if (!grpc_tcp_prepare_socket(sock)) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
+  error = grpc_tcp_prepare_socket(sock);
+  if (error != GRPC_ERROR_NONE) {
+    goto failure;
   }
 
   if (bind(sock, addr, (int)addr_len) == SOCKET_ERROR) {
-    char *addr_str;
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message);
-    gpr_free(utf8_message);
-    gpr_free(addr_str);
-    goto error;
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
+    goto failure;
   }
 
   if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "listen: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "listen");
+    goto failure;
   }
 
   sockname_len = sizeof(sockname_temp);
   if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
       SOCKET_ERROR) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
-    gpr_free(utf8_message);
-    goto error;
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname");
+    goto failure;
   }
 
-  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+  return GRPC_ERROR_NONE;
 
-error:
+failure:
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
+  char *tgtaddr = grpc_sockaddr_to_uri(addr);
+  grpc_error *final_error = grpc_error_set_int(
+      grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING(
+                             "Failed to prepare server socket", &error, 1),
+                         GRPC_ERROR_STR_TARGET_ADDRESS, tgtaddr),
+      GRPC_ERROR_INT_FD, (intptr_t)sock);
+  gpr_free(tgtaddr);
+  GRPC_ERROR_UNREF(error);
   if (sock != INVALID_SOCKET) closesocket(sock);
-  return -1;
+  return error;
 }
 
 static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
@@ -251,26 +252,23 @@
 
 /* In order to do an async accept, we need to create a socket first which
    will be the one assigned to the new incoming connection. */
-static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
+static grpc_error *start_accept(grpc_exec_ctx *exec_ctx,
+                                grpc_tcp_listener *port) {
   SOCKET sock = INVALID_SOCKET;
-  char *message;
-  char *utf8_message;
   BOOL success;
   DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
   DWORD bytes_received = 0;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                    WSA_FLAG_OVERLAPPED);
-
   if (sock == INVALID_SOCKET) {
-    message = "Unable to create socket: %s";
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
     goto failure;
   }
 
-  if (!grpc_tcp_prepare_socket(sock)) {
-    message = "Unable to prepare socket: %s";
-    goto failure;
-  }
+  error = grpc_tcp_prepare_socket(sock);
+  if (error != GRPC_ERROR_NONE) goto failure;
 
   /* Start the "accept" asynchronously. */
   success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0,
@@ -280,9 +278,9 @@
   /* It is possible to get an accept immediately without delay. However, we
      will still get an IOCP notification for it. So let's just ignore it. */
   if (!success) {
-    int error = WSAGetLastError();
-    if (error != ERROR_IO_PENDING) {
-      message = "AcceptEx failed: %s";
+    int last_error = WSAGetLastError();
+    if (last_error != ERROR_IO_PENDING) {
+      error = GRPC_WSA_ERROR(last_error, "AcceptEx");
       goto failure;
     }
   }
@@ -291,9 +289,10 @@
      immediately process an accept that happened in the meantime. */
   port->new_socket = sock;
   grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
-  return;
+  return error;
 
 failure:
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
   if (port->shutting_down) {
     /* We are abandoning the listener port, take that into account to prevent
        occasional hangs on shutdown. The hang happens when sp->shutting_down
@@ -301,16 +300,15 @@
        but we fail there because the listening port has been closed in the
        meantime. */
     decrement_active_ports_and_notify(exec_ctx, port);
-    return;
+    GRPC_ERROR_UNREF(error);
+    return GRPC_ERROR_NONE;
   }
-  utf8_message = gpr_format_message(WSAGetLastError());
-  gpr_log(GPR_ERROR, message, utf8_message);
-  gpr_free(utf8_message);
   if (sock != INVALID_SOCKET) closesocket(sock);
+  return error;
 }
 
 /* Event manager callback when reads are ready. */
-static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, bool from_iocp) {
+static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_tcp_listener *sp = arg;
   grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0};
   SOCKET sock = sp->new_socket;
@@ -328,7 +326,10 @@
   /* The general mechanism for shutting down is to queue abortion calls. While
      this is necessary in the read/write case, it's useless for the accept
      case. We only need to adjust the pending callback count */
-  if (!from_iocp) {
+  if (error != GRPC_ERROR_NONE) {
+    const char *msg = grpc_error_string(error);
+    gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
+    grpc_error_free_string(msg);
     return;
   }
 
@@ -387,21 +388,20 @@
      the former socked we created has now either been destroy or assigned
      to the new connection. We need to create a new one for the next
      connection. */
-  start_accept(exec_ctx, sp);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp)));
 }
 
-static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
-                                               const struct sockaddr *addr,
-                                               size_t addr_len,
-                                               unsigned port_index) {
+static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
+                                        const struct sockaddr *addr,
+                                        size_t addr_len, unsigned port_index,
+                                        grpc_tcp_listener **listener) {
   grpc_tcp_listener *sp = NULL;
   int port;
   int status;
   GUID guid = WSAID_ACCEPTEX;
   DWORD ioctl_num_bytes;
   LPFN_ACCEPTEX AcceptEx;
-
-  if (sock == INVALID_SOCKET) return NULL;
+  grpc_error *error = GRPC_ERROR_NONE;
 
   /* We need to grab the AcceptEx pointer for that port, as it may be
      interface-dependent. We'll cache it to avoid doing that again. */
@@ -417,44 +417,49 @@
     return NULL;
   }
 
-  port = prepare_socket(sock, addr, addr_len);
-  if (port >= 0) {
-    gpr_mu_lock(&s->mu);
-    GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-    sp = gpr_malloc(sizeof(grpc_tcp_listener));
-    sp->next = NULL;
-    if (s->head == NULL) {
-      s->head = sp;
-    } else {
-      s->tail->next = sp;
-    }
-    s->tail = sp;
-    sp->server = s;
-    sp->socket = grpc_winsocket_create(sock, "listener");
-    sp->shutting_down = 0;
-    sp->AcceptEx = AcceptEx;
-    sp->new_socket = INVALID_SOCKET;
-    sp->port = port;
-    sp->port_index = port_index;
-    grpc_closure_init(&sp->on_accept, on_accept, sp);
-    GPR_ASSERT(sp->socket);
-    gpr_mu_unlock(&s->mu);
+  error = prepare_socket(sock, addr, addr_len, &port);
+  if (error != GRPC_ERROR_NONE) {
+    return error;
   }
 
-  return sp;
+  GPR_ASSERT(port >= 0);
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
+  sp = gpr_malloc(sizeof(grpc_tcp_listener));
+  sp->next = NULL;
+  if (s->head == NULL) {
+    s->head = sp;
+  } else {
+    s->tail->next = sp;
+  }
+  s->tail = sp;
+  sp->server = s;
+  sp->socket = grpc_winsocket_create(sock, "listener");
+  sp->shutting_down = 0;
+  sp->AcceptEx = AcceptEx;
+  sp->new_socket = INVALID_SOCKET;
+  sp->port = port;
+  sp->port_index = port_index;
+  grpc_closure_init(&sp->on_accept, on_accept, sp);
+  GPR_ASSERT(sp->socket);
+  gpr_mu_unlock(&s->mu);
+  *listener = sp;
+
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
-  grpc_tcp_listener *sp;
+grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
+                                     size_t addr_len, int *port) {
+  grpc_tcp_listener *sp = NULL;
   SOCKET sock;
   struct sockaddr_in6 addr6_v4mapped;
   struct sockaddr_in6 wildcard;
   struct sockaddr *allocated_addr = NULL;
   struct sockaddr_storage sockname_temp;
   socklen_t sockname_len;
-  int port;
   unsigned port_index = 0;
+  grpc_error *error = GRPC_ERROR_NONE;
+
   if (s->tail != NULL) {
     port_index = s->tail->port_index + 1;
   }
@@ -466,11 +471,11 @@
       sockname_len = sizeof(sockname_temp);
       if (0 == getsockname(sp->socket->socket,
                            (struct sockaddr *)&sockname_temp, &sockname_len)) {
-        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
-        if (port > 0) {
+        *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+        if (*port > 0) {
           allocated_addr = gpr_malloc(addr_len);
           memcpy(allocated_addr, addr, addr_len);
-          grpc_sockaddr_set_port(allocated_addr, port);
+          grpc_sockaddr_set_port(allocated_addr, *port);
           addr = allocated_addr;
           break;
         }
@@ -484,8 +489,8 @@
   }
 
   /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcard6(port, &wildcard);
+  if (grpc_sockaddr_is_wildcard(addr, port)) {
+    grpc_sockaddr_make_wildcard6(*port, &wildcard);
 
     addr = (struct sockaddr *)&wildcard;
     addr_len = sizeof(wildcard);
@@ -494,19 +499,26 @@
   sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                    WSA_FLAG_OVERLAPPED);
   if (sock == INVALID_SOCKET) {
-    char *utf8_message = gpr_format_message(WSAGetLastError());
-    gpr_log(GPR_ERROR, "unable to create socket: %s", utf8_message);
-    gpr_free(utf8_message);
+    error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
+    goto done;
   }
 
-  sp = add_socket_to_server(s, sock, addr, addr_len, port_index);
+  error = add_socket_to_server(s, sock, addr, addr_len, port_index, &sp);
+
+done:
   gpr_free(allocated_addr);
 
-  if (sp) {
-    return sp->port;
+  if (error != GRPC_ERROR_NONE) {
+    grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING(
+        "Failed to add port to server", &error, 1);
+    GRPC_ERROR_UNREF(error);
+    error = error_out;
+    *port = -1;
   } else {
-    return -1;
+    GPR_ASSERT(sp != NULL);
+    *port = sp->port;
   }
+  return error;
 }
 
 void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
@@ -521,7 +533,7 @@
   s->on_accept_cb = on_accept_cb;
   s->on_accept_cb_arg = on_accept_cb_arg;
   for (sp = s->head; sp; sp = sp->next) {
-    start_accept(exec_ctx, sp);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp)));
     s->active_ports++;
   }
   gpr_mu_unlock(&s->mu);
diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c
index f44bf5f..b2af803 100644
--- a/src/core/lib/iomgr/tcp_windows.c
+++ b/src/core/lib/iomgr/tcp_windows.c
@@ -61,27 +61,34 @@
 #define GRPC_FIONBIO FIONBIO
 #endif
 
-static int set_non_block(SOCKET sock) {
+static grpc_error *set_non_block(SOCKET sock) {
   int status;
   uint32_t param = 1;
   DWORD ret;
   status = WSAIoctl(sock, GRPC_FIONBIO, &param, sizeof(param), NULL, 0, &ret,
                     NULL, NULL);
-  return status == 0;
+  return status == 0
+             ? GRPC_ERROR_NONE
+             : GRPC_WSA_ERROR(WSAGetLastError(), "WSAIoctl(GRPC_FIONBIO)");
 }
 
-static int set_dualstack(SOCKET sock) {
+static grpc_error *set_dualstack(SOCKET sock) {
   int status;
   unsigned long param = 0;
   status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&param,
                       sizeof(param));
-  return status == 0;
+  return status == 0
+             ? GRPC_ERROR_NONE
+             : GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)");
 }
 
-int grpc_tcp_prepare_socket(SOCKET sock) {
-  if (!set_non_block(sock)) return 0;
-  if (!set_dualstack(sock)) return 0;
-  return 1;
+grpc_error *grpc_tcp_prepare_socket(SOCKET sock) {
+  grpc_error *err;
+  err = set_non_block(sock);
+  if (err != GRPC_ERROR_NONE) return err;
+  err = set_dualstack(sock);
+  if (err != GRPC_ERROR_NONE) return err;
+  return GRPC_ERROR_NONE;
 }
 
 typedef struct grpc_tcp {
@@ -148,39 +155,35 @@
 #endif
 
 /* Asynchronous callback from the IOCP, or the background thread. */
-static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) {
   grpc_tcp *tcp = tcpp;
   grpc_closure *cb = tcp->read_cb;
   grpc_winsocket *socket = tcp->socket;
   gpr_slice sub;
   grpc_winsocket_callback_info *info = &socket->read_info;
 
-  if (success) {
+  GRPC_ERROR_REF(error);
+
+  if (error == GRPC_ERROR_NONE) {
     if (info->wsa_error != 0 && !tcp->shutting_down) {
-      if (info->wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      success = 0;
+      char *utf8_message = gpr_format_message(info->wsa_error);
+      error = GRPC_ERROR_CREATE(utf8_message);
+      gpr_free(utf8_message);
       gpr_slice_unref(tcp->read_slice);
     } else {
       if (info->bytes_transfered != 0 && !tcp->shutting_down) {
         sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
         gpr_slice_buffer_add(tcp->read_slices, sub);
-        success = 1;
       } else {
         gpr_slice_unref(tcp->read_slice);
-        success = 0;
+        error = GRPC_ERROR_CREATE("End of TCP stream");
       }
     }
   }
 
   tcp->read_cb = NULL;
   TCP_UNREF(tcp, "read");
-  if (cb) {
-    cb->cb(exec_ctx, cb->cb_arg, success);
-  }
+  grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
 }
 
 static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
@@ -194,7 +197,8 @@
   WSABUF buffer;
 
   if (tcp->shutting_down) {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb,
+                        GRPC_ERROR_CREATE("TCP socket is shutting down"), NULL);
     return;
   }
 
@@ -218,7 +222,7 @@
   /* Did we get data immediately ? Yay. */
   if (info->wsa_error != WSAEWOULDBLOCK) {
     info->bytes_transfered = bytes_read;
-    grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &tcp->on_read, GRPC_ERROR_NONE, NULL);
     return;
   }
 
@@ -231,7 +235,8 @@
     int wsa_error = WSAGetLastError();
     if (wsa_error != WSA_IO_PENDING) {
       info->wsa_error = wsa_error;
-      grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, &tcp->on_read,
+                          GRPC_WSA_ERROR(info->wsa_error, "WSARecv"), NULL);
       return;
     }
   }
@@ -240,32 +245,29 @@
 }
 
 /* Asynchronous callback from the IOCP, or the background thread. */
-static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
+static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) {
   grpc_tcp *tcp = (grpc_tcp *)tcpp;
   grpc_winsocket *handle = tcp->socket;
   grpc_winsocket_callback_info *info = &handle->write_info;
   grpc_closure *cb;
 
+  GRPC_ERROR_REF(error);
+
   gpr_mu_lock(&tcp->mu);
   cb = tcp->write_cb;
   tcp->write_cb = NULL;
   gpr_mu_unlock(&tcp->mu);
 
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     if (info->wsa_error != 0) {
-      if (info->wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-      success = 0;
+      error = GRPC_WSA_ERROR(info->wsa_error, "WSASend");
     } else {
       GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length);
     }
   }
 
   TCP_UNREF(tcp, "write");
-  cb->cb(exec_ctx, cb->cb_arg, success);
+  grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
 }
 
 /* Initiates a write. */
@@ -283,7 +285,8 @@
   size_t len;
 
   if (tcp->shutting_down) {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb,
+                        GRPC_ERROR_CREATE("TCP socket is shutting down"), NULL);
     return;
   }
 
@@ -311,19 +314,10 @@
      connection that has its send queue filled up. But if we don't, then we can
      avoid doing an async write operation at all. */
   if (info->wsa_error != WSAEWOULDBLOCK) {
-    bool ok = false;
-    if (status == 0) {
-      ok = true;
-      GPR_ASSERT(bytes_sent == tcp->write_slices->length);
-    } else {
-      if (info->wsa_error != WSAECONNRESET) {
-        char *utf8_message = gpr_format_message(info->wsa_error);
-        gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
-        gpr_free(utf8_message);
-      }
-    }
-    if (allocated) gpr_free(allocated);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);
+    grpc_error *error = status == 0
+                            ? GRPC_ERROR_NONE
+                            : GRPC_WSA_ERROR(info->wsa_error, "WSASend");
+    grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
     return;
   }
 
@@ -340,7 +334,8 @@
     int wsa_error = WSAGetLastError();
     if (wsa_error != WSA_IO_PENDING) {
       TCP_UNREF(tcp, "write");
-      grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, cb, GRPC_WSA_ERROR(wsa_error, "WSASend"),
+                          NULL);
       return;
     }
   }
diff --git a/src/core/lib/iomgr/tcp_windows.h b/src/core/lib/iomgr/tcp_windows.h
index a2f58ed..86d7772 100644
--- a/src/core/lib/iomgr/tcp_windows.h
+++ b/src/core/lib/iomgr/tcp_windows.h
@@ -52,6 +52,6 @@
  */
 grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string);
 
-int grpc_tcp_prepare_socket(SOCKET sock);
+grpc_error *grpc_tcp_prepare_socket(SOCKET sock);
 
 #endif /* GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H */
diff --git a/src/core/lib/iomgr/timer.c b/src/core/lib/iomgr/timer.c
index 69d3bab..9975fa1 100644
--- a/src/core/lib/iomgr/timer.c
+++ b/src/core/lib/iomgr/timer.c
@@ -73,7 +73,7 @@
 static bool g_initialized = false;
 
 static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                                   gpr_timespec *next, int success);
+                                   gpr_timespec *next, grpc_error *error);
 
 static gpr_timespec compute_min_deadline(shard_type *shard) {
   return grpc_timer_heap_is_empty(&shard->heap)
@@ -105,7 +105,8 @@
 
 void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
   int i;
-  run_some_expired_timers(exec_ctx, gpr_inf_future(g_clock_type), NULL, 0);
+  run_some_expired_timers(exec_ctx, gpr_inf_future(g_clock_type), NULL,
+                          GRPC_ERROR_CREATE("Timer list shutdown"));
   for (i = 0; i < NUM_SHARDS; i++) {
     shard_type *shard = &g_shards[i];
     gpr_mu_destroy(&shard->mu);
@@ -185,13 +186,16 @@
 
   if (!g_initialized) {
     timer->triggered = 1;
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
+    grpc_exec_ctx_sched(
+        exec_ctx, &timer->closure,
+        GRPC_ERROR_CREATE("Attempt to create timer before initialization"),
+        NULL);
     return;
   }
 
   if (gpr_time_cmp(deadline, now) <= 0) {
     timer->triggered = 1;
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_NONE, NULL);
     return;
   }
 
@@ -235,10 +239,15 @@
 }
 
 void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
+  if (!g_initialized) {
+    /* must have already been cancelled, also the shard mutex is invalid */
+    return;
+  }
+
   shard_type *shard = &g_shards[shard_idx(timer)];
   gpr_mu_lock(&shard->mu);
   if (!timer->triggered) {
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_CANCELLED, NULL);
     timer->triggered = 1;
     if (timer->heap_index == INVALID_HEAP_INDEX) {
       list_remove(timer);
@@ -299,12 +308,12 @@
 /* REQUIRES: shard->mu unlocked */
 static size_t pop_timers(grpc_exec_ctx *exec_ctx, shard_type *shard,
                          gpr_timespec now, gpr_timespec *new_min_deadline,
-                         int success) {
+                         grpc_error *error) {
   size_t n = 0;
   grpc_timer *timer;
   gpr_mu_lock(&shard->mu);
   while ((timer = pop_one(shard, now))) {
-    grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, success, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &timer->closure, GRPC_ERROR_REF(error), NULL);
     n++;
   }
   *new_min_deadline = compute_min_deadline(shard);
@@ -313,7 +322,7 @@
 }
 
 static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                                   gpr_timespec *next, int success) {
+                                   gpr_timespec *next, grpc_error *error) {
   size_t n = 0;
 
   /* TODO(ctiller): verify that there are any timers (atomically) here */
@@ -327,8 +336,8 @@
       /* For efficiency, we pop as many available timers as we can from the
          shard.  This may violate perfect timer deadline ordering, but that
          shouldn't be a big deal because we don't make ordering guarantees. */
-      n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline,
-                      success);
+      n +=
+          pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline, error);
 
       /* An grpc_timer_init() on the shard could intervene here, adding a new
          timer that is earlier than new_min_deadline.  However,
@@ -359,6 +368,8 @@
         *next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
   }
 
+  GRPC_ERROR_UNREF(error);
+
   return (int)n;
 }
 
@@ -367,5 +378,7 @@
   GPR_ASSERT(now.clock_type == g_clock_type);
   return run_some_expired_timers(
       exec_ctx, now, next,
-      gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
+      gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0
+          ? GRPC_ERROR_NONE
+          : GRPC_ERROR_CREATE("Shutting down timer system"));
 }
diff --git a/src/core/lib/iomgr/unix_sockets_posix.c b/src/core/lib/iomgr/unix_sockets_posix.c
index 5767c85..0e7670e 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.c
+++ b/src/core/lib/iomgr/unix_sockets_posix.c
@@ -47,17 +47,18 @@
   GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
 }
 
-grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name) {
+grpc_error *grpc_resolve_unix_domain_address(const char *name,
+                                             grpc_resolved_addresses **addrs) {
   struct sockaddr_un *un;
 
-  grpc_resolved_addresses *addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
-  addrs->naddrs = 1;
-  addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
-  un = (struct sockaddr_un *)addrs->addrs->addr;
+  *addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
+  (*addrs)->naddrs = 1;
+  (*addrs)->addrs = gpr_malloc(sizeof(grpc_resolved_address));
+  un = (struct sockaddr_un *)(*addrs)->addrs->addr;
   un->sun_family = AF_UNIX;
   strcpy(un->sun_path, name);
-  addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
-  return addrs;
+  (*addrs)->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
+  return GRPC_ERROR_NONE;
 }
 
 int grpc_is_unix_socket(const struct sockaddr *addr) {
diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h
index 6758c49..db0516d 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.h
+++ b/src/core/lib/iomgr/unix_sockets_posix.h
@@ -43,7 +43,8 @@
 
 void grpc_create_socketpair_if_unix(int sv[2]);
 
-grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name);
+grpc_error *grpc_resolve_unix_domain_address(
+    const char *name, grpc_resolved_addresses **addresses);
 
 int grpc_is_unix_socket(const struct sockaddr *addr);
 
diff --git a/src/core/lib/iomgr/unix_sockets_posix_noop.c b/src/core/lib/iomgr/unix_sockets_posix_noop.c
index d309527..56b47c3 100644
--- a/src/core/lib/iomgr/unix_sockets_posix_noop.c
+++ b/src/core/lib/iomgr/unix_sockets_posix_noop.c
@@ -44,8 +44,10 @@
   GPR_ASSERT(0);
 }
 
-grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name) {
-  return NULL;
+grpc_error *grpc_resolve_unix_domain_address(
+    const char *name, grpc_resolved_addresses **addresses) {
+  *addresses = NULL;
+  return GRPC_ERROR_CREATE("Unix domain sockets are not supported on Windows");
 }
 
 int grpc_is_unix_socket(const struct sockaddr *addr) { return false; }
diff --git a/src/core/lib/iomgr/wakeup_fd_eventfd.c b/src/core/lib/iomgr/wakeup_fd_eventfd.c
index 8a772ad..667b4a5 100644
--- a/src/core/lib/iomgr/wakeup_fd_eventfd.c
+++ b/src/core/lib/iomgr/wakeup_fd_eventfd.c
@@ -44,29 +44,39 @@
 #include "src/core/lib/iomgr/wakeup_fd_posix.h"
 #include "src/core/lib/profiling/timers.h"
 
-static void eventfd_create(grpc_wakeup_fd* fd_info) {
+static grpc_error* eventfd_create(grpc_wakeup_fd* fd_info) {
   int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-  /* TODO(klempner): Handle failure more gracefully */
-  GPR_ASSERT(efd >= 0);
+  if (efd < 0) {
+    return GRPC_OS_ERROR(errno, "eventfd");
+  }
   fd_info->read_fd = efd;
   fd_info->write_fd = -1;
+  return GRPC_ERROR_NONE;
 }
 
-static void eventfd_consume(grpc_wakeup_fd* fd_info) {
+static grpc_error* eventfd_consume(grpc_wakeup_fd* fd_info) {
   eventfd_t value;
   int err;
   do {
     err = eventfd_read(fd_info->read_fd, &value);
   } while (err < 0 && errno == EINTR);
+  if (err < 0 && errno != EAGAIN) {
+    return GRPC_OS_ERROR(errno, "eventfd_read");
+  }
+  return GRPC_ERROR_NONE;
 }
 
-static void eventfd_wakeup(grpc_wakeup_fd* fd_info) {
+static grpc_error* eventfd_wakeup(grpc_wakeup_fd* fd_info) {
   int err;
   GPR_TIMER_BEGIN("eventfd_wakeup", 0);
   do {
     err = eventfd_write(fd_info->read_fd, 1);
   } while (err < 0 && errno == EINTR);
+  if (err < 0) {
+    return GRPC_OS_ERROR(errno, "eventfd_write");
+  }
   GPR_TIMER_END("eventfd_wakeup", 0);
+  return GRPC_ERROR_NONE;
 }
 
 static void eventfd_destroy(grpc_wakeup_fd* fd_info) {
diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.c b/src/core/lib/iomgr/wakeup_fd_pipe.c
index e9b9a01..4e5dbdc 100644
--- a/src/core/lib/iomgr/wakeup_fd_pipe.c
+++ b/src/core/lib/iomgr/wakeup_fd_pipe.c
@@ -45,7 +45,7 @@
 
 #include "src/core/lib/iomgr/socket_utils_posix.h"
 
-static void pipe_init(grpc_wakeup_fd* fd_info) {
+static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) {
   int pipefd[2];
   /* TODO(klempner): Make this nonfatal */
   int r = pipe(pipefd);
@@ -53,36 +53,40 @@
     gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno));
     abort();
   }
-  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1));
-  GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1));
+  grpc_error* err;
+  err = grpc_set_socket_nonblocking(pipefd[0], 1);
+  if (err != GRPC_ERROR_NONE) return err;
+  err = grpc_set_socket_nonblocking(pipefd[1], 1);
+  if (err != GRPC_ERROR_NONE) return err;
   fd_info->read_fd = pipefd[0];
   fd_info->write_fd = pipefd[1];
+  return GRPC_ERROR_NONE;
 }
 
-static void pipe_consume(grpc_wakeup_fd* fd_info) {
+static grpc_error* pipe_consume(grpc_wakeup_fd* fd_info) {
   char buf[128];
   ssize_t r;
 
   for (;;) {
     r = read(fd_info->read_fd, buf, sizeof(buf));
     if (r > 0) continue;
-    if (r == 0) return;
+    if (r == 0) return GRPC_ERROR_NONE;
     switch (errno) {
       case EAGAIN:
-        return;
+        return GRPC_ERROR_NONE;
       case EINTR:
         continue;
       default:
-        gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno));
-        return;
+        return GRPC_OS_ERROR(errno, "read");
     }
   }
 }
 
-static void pipe_wakeup(grpc_wakeup_fd* fd_info) {
+static grpc_error* pipe_wakeup(grpc_wakeup_fd* fd_info) {
   char c = 0;
   while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR)
     ;
+  return GRPC_ERROR_NONE;
 }
 
 static void pipe_destroy(grpc_wakeup_fd* fd_info) {
diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c
index 525369c..046208a 100644
--- a/src/core/lib/iomgr/wakeup_fd_posix.c
+++ b/src/core/lib/iomgr/wakeup_fd_posix.c
@@ -53,16 +53,16 @@
 
 void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; }
 
-void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->init(fd_info);
+grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {
+  return wakeup_fd_vtable->init(fd_info);
 }
 
-void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->consume(fd_info);
+grpc_error *grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) {
+  return wakeup_fd_vtable->consume(fd_info);
 }
 
-void grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) {
-  wakeup_fd_vtable->wakeup(fd_info);
+grpc_error *grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) {
+  return wakeup_fd_vtable->wakeup(fd_info);
 }
 
 void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) {
diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h
index 6b069c1..e269f24 100644
--- a/src/core/lib/iomgr/wakeup_fd_posix.h
+++ b/src/core/lib/iomgr/wakeup_fd_posix.h
@@ -62,6 +62,8 @@
 #ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H
 #define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_POSIX_H
 
+#include "src/core/lib/iomgr/error.h"
+
 void grpc_wakeup_fd_global_init(void);
 void grpc_wakeup_fd_global_destroy(void);
 
@@ -72,9 +74,9 @@
 typedef struct grpc_wakeup_fd grpc_wakeup_fd;
 
 typedef struct grpc_wakeup_fd_vtable {
-  void (*init)(grpc_wakeup_fd* fd_info);
-  void (*consume)(grpc_wakeup_fd* fd_info);
-  void (*wakeup)(grpc_wakeup_fd* fd_info);
+  grpc_error* (*init)(grpc_wakeup_fd* fd_info);
+  grpc_error* (*consume)(grpc_wakeup_fd* fd_info);
+  grpc_error* (*wakeup)(grpc_wakeup_fd* fd_info);
   void (*destroy)(grpc_wakeup_fd* fd_info);
   /* Must be called before calling any other functions */
   int (*check_availability)(void);
@@ -89,9 +91,10 @@
 
 #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd)
 
-void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info);
-void grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info);
-void grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info);
+grpc_error* grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT;
+grpc_error* grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info)
+    GRPC_MUST_USE_RESULT;
+grpc_error* grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT;
 void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info);
 
 /* Defined in some specialized implementation's .c file, or by
diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h
index eeca8c0..5cc40ee 100644
--- a/src/core/lib/iomgr/workqueue.h
+++ b/src/core/lib/iomgr/workqueue.h
@@ -50,7 +50,8 @@
 /* grpc_workqueue is forward declared in exec_ctx.h */
 
 /** Create a work queue */
-grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx);
+grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx,
+                                  grpc_workqueue **workqueue);
 
 void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue);
 
@@ -77,7 +78,7 @@
                                    grpc_pollset *pollset);
 
 /** Add a work item to a workqueue */
-void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
-                         int success);
+void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
+                            grpc_closure *closure, grpc_error *error);
 
 #endif /* GRPC_CORE_LIB_IOMGR_WORKQUEUE_H */
diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c
index 80e7a0b..45e0f60 100644
--- a/src/core/lib/iomgr/workqueue_posix.c
+++ b/src/core/lib/iomgr/workqueue_posix.c
@@ -45,22 +45,27 @@
 
 #include "src/core/lib/iomgr/ev_posix.h"
 
-static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success);
+static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
 
-grpc_workqueue *grpc_workqueue_create(grpc_exec_ctx *exec_ctx) {
+grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx,
+                                  grpc_workqueue **workqueue) {
   char name[32];
-  grpc_workqueue *workqueue = gpr_malloc(sizeof(grpc_workqueue));
-  gpr_ref_init(&workqueue->refs, 1);
-  gpr_mu_init(&workqueue->mu);
-  workqueue->closure_list.head = workqueue->closure_list.tail = NULL;
-  grpc_wakeup_fd_init(&workqueue->wakeup_fd);
-  sprintf(name, "workqueue:%p", (void *)workqueue);
-  workqueue->wakeup_read_fd =
-      grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&workqueue->wakeup_fd), name);
-  grpc_closure_init(&workqueue->read_closure, on_readable, workqueue);
-  grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
-                         &workqueue->read_closure);
-  return workqueue;
+  *workqueue = gpr_malloc(sizeof(grpc_workqueue));
+  gpr_ref_init(&(*workqueue)->refs, 1);
+  gpr_mu_init(&(*workqueue)->mu);
+  (*workqueue)->closure_list.head = (*workqueue)->closure_list.tail = NULL;
+  grpc_error *err = grpc_wakeup_fd_init(&(*workqueue)->wakeup_fd);
+  if (err != GRPC_ERROR_NONE) {
+    gpr_free(*workqueue);
+    return err;
+  }
+  sprintf(name, "workqueue:%p", (void *)(*workqueue));
+  (*workqueue)->wakeup_read_fd = grpc_fd_create(
+      GRPC_WAKEUP_FD_GET_READ_FD(&(*workqueue)->wakeup_fd), name);
+  grpc_closure_init(&(*workqueue)->read_closure, on_readable, *workqueue);
+  grpc_fd_notify_on_read(exec_ctx, (*workqueue)->wakeup_read_fd,
+                         &(*workqueue)->read_closure);
+  return GRPC_ERROR_NONE;
 }
 
 static void workqueue_destroy(grpc_exec_ctx *exec_ctx,
@@ -103,17 +108,14 @@
 
 void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
   gpr_mu_lock(&workqueue->mu);
-  if (grpc_closure_list_empty(workqueue->closure_list)) {
-    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
-  }
   grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
   gpr_mu_unlock(&workqueue->mu);
 }
 
-static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_workqueue *workqueue = arg;
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     gpr_mu_destroy(&workqueue->mu);
     /* HACK: let wakeup_fd code know that we stole the fd */
     workqueue->wakeup_fd.read_fd = 0;
@@ -123,20 +125,32 @@
   } else {
     gpr_mu_lock(&workqueue->mu);
     grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
-    grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
+    error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
     gpr_mu_unlock(&workqueue->mu);
-    grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
-                           &workqueue->read_closure);
+    if (error == GRPC_ERROR_NONE) {
+      grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,
+                             &workqueue->read_closure);
+    } else {
+      /* recurse to get error handling */
+      on_readable(exec_ctx, arg, error);
+    }
   }
 }
 
-void grpc_workqueue_push(grpc_workqueue *workqueue, grpc_closure *closure,
-                         int success) {
+void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
+                            grpc_closure *closure, grpc_error *error) {
+  grpc_error *push_error = GRPC_ERROR_NONE;
   gpr_mu_lock(&workqueue->mu);
   if (grpc_closure_list_empty(workqueue->closure_list)) {
-    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
+    push_error = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
   }
-  grpc_closure_list_add(&workqueue->closure_list, closure, success);
+  grpc_closure_list_append(&workqueue->closure_list, closure, error);
+  if (push_error != GRPC_ERROR_NONE) {
+    const char *msg = grpc_error_string(push_error);
+    gpr_log(GPR_ERROR, "Failed to push to workqueue: %s", msg);
+    grpc_error_free_string(msg);
+    grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
+  }
   gpr_mu_unlock(&workqueue->mu);
 }
 
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index f45a8d8..0eadaec 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -58,6 +58,7 @@
     void *user_data) {
   grpc_credentials_metadata_request *r =
       gpr_malloc(sizeof(grpc_credentials_metadata_request));
+  memset(&r->response, 0, sizeof(r->response));
   r->creds = grpc_call_credentials_ref(creds);
   r->cb = cb;
   r->user_data = user_data;
@@ -67,6 +68,7 @@
 void grpc_credentials_metadata_request_destroy(
     grpc_credentials_metadata_request *r) {
   grpc_call_credentials_unref(r->creds);
+  grpc_http_response_destroy(&r->response);
   gpr_free(r);
 }
 
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index 15dcfe4..ce235e3 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -225,6 +225,7 @@
 typedef struct {
   grpc_call_credentials *creds;
   grpc_credentials_metadata_cb cb;
+  grpc_http_response response;
   void *user_data;
 } grpc_credentials_metadata_request;
 
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index 005777d..ee6d964 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -95,7 +95,7 @@
 }
 
 static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
-                                          void *user_data, bool success) {
+                                          void *user_data, grpc_error *error) {
   grpc_credentials_metadata_request *r =
       (grpc_credentials_metadata_request *)user_data;
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
@@ -113,8 +113,9 @@
   if (c->is_async) {
     grpc_credentials_metadata_request *cb_arg =
         grpc_credentials_metadata_request_create(creds, cb, user_data);
-    grpc_executor_enqueue(
-        grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true);
+    grpc_executor_push(
+        grpc_closure_create(on_simulated_token_fetch_done, cb_arg),
+        GRPC_ERROR_NONE);
   } else {
     cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
   }
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index 98df68e..312a3d4 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -41,11 +41,12 @@
 
 #include "src/core/lib/http/httpcli.h"
 #include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/polling_entity.h"
 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
 #include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/api_trace.h"
 
 /* -- Constants. -- */
@@ -66,18 +67,20 @@
   grpc_polling_entity pollent;
   int is_done;
   int success;
+  grpc_http_response response;
 } compute_engine_detector;
 
-static void on_compute_engine_detection_http_response(
-    grpc_exec_ctx *exec_ctx, void *user_data,
-    const grpc_http_response *response) {
+static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx,
+                                                      void *user_data,
+                                                      grpc_error *error) {
   compute_engine_detector *detector = (compute_engine_detector *)user_data;
-  if (response != NULL && response->status == 200 && response->hdr_count > 0) {
+  if (error == GRPC_ERROR_NONE && detector->response.status == 200 &&
+      detector->response.hdr_count > 0) {
     /* Internet providers can return a generic response to all requests, so
        it is necessary to check that metadata header is present also. */
     size_t i;
-    for (i = 0; i < response->hdr_count; i++) {
-      grpc_http_header *header = &response->hdrs[i];
+    for (i = 0; i < detector->response.hdr_count; i++) {
+      grpc_http_header *header = &detector->response.hdrs[i];
       if (strcmp(header->key, "Metadata-Flavor") == 0 &&
           strcmp(header->value, "Google") == 0) {
         detector->success = 1;
@@ -87,11 +90,13 @@
   }
   gpr_mu_lock(g_polling_mu);
   detector->is_done = 1;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL);
+  GRPC_LOG_IF_ERROR(
+      "Pollset kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent), NULL));
   gpr_mu_unlock(g_polling_mu);
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) {
   grpc_pollset_destroy(p);
 }
 
@@ -112,6 +117,7 @@
   detector.is_done = 0;
   detector.success = 0;
 
+  memset(&detector.response, 0, sizeof(detector.response));
   memset(&request, 0, sizeof(grpc_httpcli_request));
   request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
   request.http.path = "/";
@@ -121,18 +127,25 @@
   grpc_httpcli_get(
       &exec_ctx, &context, &detector.pollent, &request,
       gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
-      on_compute_engine_detection_http_response, &detector);
+      grpc_closure_create(on_compute_engine_detection_http_response, &detector),
+      &detector.response);
 
-  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_exec_ctx_flush(&exec_ctx);
 
   /* Block until we get the response. This is not ideal but this should only be
      called once for the lifetime of the process by the default credentials. */
   gpr_mu_lock(g_polling_mu);
   while (!detector.is_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&detector.pollent),
-                      &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx,
+                              grpc_polling_entity_pollset(&detector.pollent),
+                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                              gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
+      detector.is_done = 1;
+      detector.success = 0;
+    }
   }
   gpr_mu_unlock(g_polling_mu);
 
@@ -146,24 +159,37 @@
   g_polling_mu = NULL;
 
   gpr_free(grpc_polling_entity_pollset(&detector.pollent));
+  grpc_http_response_destroy(&detector.response);
 
   return detector.success;
 }
 
 /* Takes ownership of creds_path if not NULL. */
-static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
+static grpc_error *create_default_creds_from_path(
+    char *creds_path, grpc_call_credentials **creds) {
   grpc_json *json = NULL;
   grpc_auth_json_key key;
   grpc_auth_refresh_token token;
   grpc_call_credentials *result = NULL;
   gpr_slice creds_data = gpr_empty_slice();
-  int file_ok = 0;
-  if (creds_path == NULL) goto end;
-  creds_data = gpr_load_file(creds_path, 0, &file_ok);
-  if (!file_ok) goto end;
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (creds_path == NULL) {
+    error = GRPC_ERROR_CREATE("creds_path unset");
+    goto end;
+  }
+  error = grpc_load_file(creds_path, 0, &creds_data);
+  if (error != GRPC_ERROR_NONE) {
+    goto end;
+  }
   json = grpc_json_parse_string_with_len(
       (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
-  if (json == NULL) goto end;
+  if (json == NULL) {
+    char *dump = gpr_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    error = grpc_error_set_str(GRPC_ERROR_CREATE("Failed to parse JSON"),
+                               GRPC_ERROR_STR_RAW_BYTES, dump);
+    gpr_free(dump);
+    goto end;
+  }
 
   /* First, try an auth json key. */
   key = grpc_auth_json_key_create_from_json(json);
@@ -171,6 +197,11 @@
     result =
         grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
             key, grpc_max_auth_token_lifetime());
+    if (result == NULL) {
+      error = GRPC_ERROR_CREATE(
+          "grpc_service_account_jwt_access_credentials_create_from_auth_json_"
+          "key failed");
+    }
     goto end;
   }
 
@@ -179,19 +210,28 @@
   if (grpc_auth_refresh_token_is_valid(&token)) {
     result =
         grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
+    if (result == NULL) {
+      error = GRPC_ERROR_CREATE(
+          "grpc_refresh_token_credentials_create_from_auth_refresh_token "
+          "failed");
+    }
     goto end;
   }
 
 end:
+  GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1);
   if (creds_path != NULL) gpr_free(creds_path);
   gpr_slice_unref(creds_data);
   if (json != NULL) grpc_json_destroy(json);
-  return result;
+  *creds = result;
+  return error;
 }
 
 grpc_channel_credentials *grpc_google_default_credentials_create(void) {
   grpc_channel_credentials *result = NULL;
   grpc_call_credentials *call_creds = NULL;
+  grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials");
+  grpc_error *err;
 
   GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
 
@@ -205,14 +245,16 @@
   }
 
   /* First, try the environment variable. */
-  call_creds = create_default_creds_from_path(
-      gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
-  if (call_creds != NULL) goto end;
+  err = create_default_creds_from_path(
+      gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
+  if (err == GRPC_ERROR_NONE) goto end;
+  error = grpc_error_add_child(error, err);
 
   /* Then the well-known file. */
-  call_creds = create_default_creds_from_path(
-      grpc_get_well_known_google_credentials_file_path());
-  if (call_creds != NULL) goto end;
+  err = create_default_creds_from_path(
+      grpc_get_well_known_google_credentials_file_path(), &call_creds);
+  if (err == GRPC_ERROR_NONE) goto end;
+  error = grpc_error_add_child(error, err);
 
   /* At last try to see if we're on compute engine (do the detection only once
      since it requires a network test). */
@@ -221,6 +263,10 @@
     compute_engine_detection_done = 1;
     if (need_compute_engine_creds) {
       call_creds = grpc_google_compute_engine_credentials_create(NULL);
+      if (call_creds == NULL) {
+        error = grpc_error_add_child(
+            error, GRPC_ERROR_CREATE("Failed to get credentials from network"));
+      }
     }
   }
 
@@ -244,6 +290,11 @@
     }
   }
   gpr_mu_unlock(&g_state_mu);
+  if (result == NULL) {
+    GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error);
+  } else {
+    GRPC_ERROR_UNREF(error);
+  }
   return result;
 }
 
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 1f67db1..73eb2e3 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -45,6 +45,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
 #include <openssl/pem.h>
 
 /* --- Utils. --- */
@@ -320,6 +321,12 @@
 
 /* --- verifier_cb_ctx object. --- */
 
+typedef enum {
+  HTTP_RESPONSE_OPENID = 0,
+  HTTP_RESPONSE_KEYS,
+  HTTP_RESPONSE_COUNT /* must be last */
+} http_response_index;
+
 typedef struct {
   grpc_jwt_verifier *verifier;
   grpc_polling_entity pollent;
@@ -330,6 +337,7 @@
   gpr_slice signed_data;
   void *user_data;
   grpc_jwt_verification_done_cb user_cb;
+  grpc_http_response responses[HTTP_RESPONSE_COUNT];
 } verifier_cb_ctx;
 
 /* Takes ownership of the header, claims and signature. */
@@ -360,6 +368,9 @@
   gpr_slice_unref(ctx->signature);
   gpr_slice_unref(ctx->signed_data);
   jose_header_destroy(ctx->header);
+  for (size_t i = 0; i < HTTP_RESPONSE_COUNT; i++) {
+    grpc_http_response_destroy(&ctx->responses[i]);
+  }
   /* TODO: see what to do with claims... */
   gpr_free(ctx);
 }
@@ -574,9 +585,9 @@
 }
 
 static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
-                              const grpc_httpcli_response *response) {
-  grpc_json *json = json_from_http(response);
+                              grpc_error *error) {
   verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+  grpc_json *json = json_from_http(&ctx->responses[HTTP_RESPONSE_KEYS]);
   EVP_PKEY *verification_key = NULL;
   grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
   grpc_jwt_claims *claims = NULL;
@@ -615,10 +626,11 @@
 }
 
 static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       const grpc_httpcli_response *response) {
+                                       grpc_error *error) {
   const grpc_json *cur;
-  grpc_json *json = json_from_http(response);
   verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
+  const grpc_http_response *response = &ctx->responses[HTTP_RESPONSE_OPENID];
+  grpc_json *json = json_from_http(response);
   grpc_httpcli_request req;
   const char *jwks_uri;
 
@@ -644,10 +656,12 @@
   } else {
     *(req.host + (req.http.path - jwks_uri)) = '\0';
   }
+
   grpc_httpcli_get(
       exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, &req,
       gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
-      on_keys_retrieved, ctx);
+      grpc_closure_create(on_keys_retrieved, ctx),
+      &ctx->responses[HTTP_RESPONSE_KEYS]);
   grpc_json_destroy(json);
   gpr_free(req.host);
   return;
@@ -689,12 +703,13 @@
 static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
                                     verifier_cb_ctx *ctx) {
   const char *at_sign;
-  grpc_httpcli_response_cb http_cb;
+  grpc_closure *http_cb;
   char *path_prefix = NULL;
   const char *iss;
   grpc_httpcli_request req;
   memset(&req, 0, sizeof(grpc_httpcli_request));
   req.handshaker = &grpc_httpcli_ssl;
+  http_response_index rsp_idx;
 
   GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
   iss = ctx->claims->iss;
@@ -733,7 +748,8 @@
       *(path_prefix++) = '\0';
       gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
     }
-    http_cb = on_keys_retrieved;
+    http_cb = grpc_closure_create(on_keys_retrieved, ctx);
+    rsp_idx = HTTP_RESPONSE_KEYS;
   } else {
     req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
     path_prefix = strchr(req.host, '/');
@@ -744,13 +760,14 @@
       gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
                    GRPC_OPENID_CONFIG_URL_SUFFIX);
     }
-    http_cb = on_openid_config_retrieved;
+    http_cb = grpc_closure_create(on_openid_config_retrieved, ctx);
+    rsp_idx = HTTP_RESPONSE_OPENID;
   }
 
   grpc_httpcli_get(
       exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, &req,
       gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
-      http_cb, ctx);
+      http_cb, &ctx->responses[rsp_idx]);
   gpr_free(req.host);
   gpr_free(req.http.path);
   return;
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 268026b..1102553 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -216,9 +216,9 @@
   return status;
 }
 
-static void on_oauth2_token_fetcher_http_response(
-    grpc_exec_ctx *exec_ctx, void *user_data,
-    const grpc_http_response *response) {
+static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
+                                                  void *user_data,
+                                                  grpc_error *error) {
   grpc_credentials_metadata_request *r =
       (grpc_credentials_metadata_request *)user_data;
   grpc_oauth2_token_fetcher_credentials *c =
@@ -226,9 +226,11 @@
   gpr_timespec token_lifetime;
   grpc_credentials_status status;
 
+  GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error));
+
   gpr_mu_lock(&c->mu);
   status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
-      response, &c->access_token_md, &token_lifetime);
+      &r->response, &c->access_token_md, &token_lifetime);
   if (status == GRPC_CREDENTIALS_OK) {
     c->token_expiration =
         gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
@@ -296,7 +298,7 @@
 static void compute_engine_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
     grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+    grpc_iomgr_cb_func response_cb, gpr_timespec deadline) {
   grpc_http_header header = {"Metadata-Flavor", "Google"};
   grpc_httpcli_request request;
   memset(&request, 0, sizeof(grpc_httpcli_request));
@@ -305,7 +307,8 @@
   request.http.hdr_count = 1;
   request.http.hdrs = &header;
   grpc_httpcli_get(exec_ctx, httpcli_context, pollent, &request, deadline,
-                   response_cb, metadata_req);
+                   grpc_closure_create(response_cb, metadata_req),
+                   &metadata_req->response);
 }
 
 grpc_call_credentials *grpc_google_compute_engine_credentials_create(
@@ -337,7 +340,7 @@
 static void refresh_token_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
     grpc_httpcli_context *httpcli_context, grpc_polling_entity *pollent,
-    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+    grpc_iomgr_cb_func response_cb, gpr_timespec deadline) {
   grpc_google_refresh_token_credentials *c =
       (grpc_google_refresh_token_credentials *)metadata_req->creds;
   grpc_http_header header = {"Content-Type",
@@ -354,7 +357,9 @@
   request.http.hdrs = &header;
   request.handshaker = &grpc_httpcli_ssl;
   grpc_httpcli_post(exec_ctx, httpcli_context, pollent, &request, body,
-                    strlen(body), deadline, response_cb, metadata_req);
+                    strlen(body), deadline,
+                    grpc_closure_create(response_cb, metadata_req),
+                    &metadata_req->response);
   gpr_free(body);
 }
 
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 3bc8360..7f6f205 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -71,7 +71,7 @@
                                        grpc_credentials_metadata_request *req,
                                        grpc_httpcli_context *http_context,
                                        grpc_polling_entity *pollent,
-                                       grpc_httpcli_response_cb response_cb,
+                                       grpc_iomgr_cb_func cb,
                                        gpr_timespec deadline);
 typedef struct {
   grpc_call_credentials base;
diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c
index 6561f4b..b374ca7 100644
--- a/src/core/lib/security/transport/handshake.c
+++ b/src/core/lib/security/transport/handshake.c
@@ -39,8 +39,10 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/slice_buffer.h>
+#include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
+#include "src/core/lib/security/transport/tsi_error.h"
 
 #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
 
@@ -60,13 +62,16 @@
   grpc_closure on_handshake_data_sent_to_peer;
   grpc_closure on_handshake_data_received_from_peer;
   grpc_auth_context *auth_context;
+  grpc_timer timer;
+  gpr_refcount refs;
 } grpc_security_handshake;
 
 static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
-                                                 void *setup, bool success);
+                                                 void *setup,
+                                                 grpc_error *error);
 
 static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
-                                           bool success);
+                                           grpc_error *error);
 
 static void security_connector_remove_handshake(grpc_security_handshake *h) {
   GPR_ASSERT(!h->is_client_side);
@@ -95,16 +100,34 @@
   gpr_mu_unlock(&sc->mu);
 }
 
+static void unref_handshake(grpc_security_handshake *h) {
+  if (gpr_unref(&h->refs)) {
+    if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
+    if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
+    gpr_slice_buffer_destroy(&h->left_overs);
+    gpr_slice_buffer_destroy(&h->outgoing);
+    gpr_slice_buffer_destroy(&h->incoming);
+    GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
+    GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
+    gpr_free(h);
+  }
+}
+
 static void security_handshake_done(grpc_exec_ctx *exec_ctx,
                                     grpc_security_handshake *h,
-                                    int is_success) {
+                                    grpc_error *error) {
+  grpc_timer_cancel(exec_ctx, &h->timer);
   if (!h->is_client_side) {
     security_connector_remove_handshake(h);
   }
-  if (is_success) {
+  if (error == GRPC_ERROR_NONE) {
     h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
           h->auth_context);
   } else {
+    const char *msg = grpc_error_string(error);
+    gpr_log(GPR_ERROR, "Security handshake failed: %s", msg);
+    grpc_error_free_string(msg);
+
     if (h->secure_endpoint != NULL) {
       grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
       grpc_endpoint_destroy(exec_ctx, h->secure_endpoint);
@@ -113,14 +136,8 @@
     }
     h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   }
-  if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
-  if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
-  gpr_slice_buffer_destroy(&h->left_overs);
-  gpr_slice_buffer_destroy(&h->outgoing);
-  gpr_slice_buffer_destroy(&h->incoming);
-  GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
-  GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
-  gpr_free(h);
+  unref_handshake(h);
+  GRPC_ERROR_UNREF(error);
 }
 
 static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -130,17 +147,20 @@
   tsi_frame_protector *protector;
   tsi_result result;
   if (status != GRPC_SECURITY_OK) {
-    gpr_log(GPR_ERROR, "Error checking peer.");
-    security_handshake_done(exec_ctx, h, 0);
+    security_handshake_done(
+        exec_ctx, h,
+        grpc_error_set_int(GRPC_ERROR_CREATE("Error checking peer."),
+                           GRPC_ERROR_INT_SECURITY_STATUS, status));
     return;
   }
   h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
   result =
       tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
   if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
+    security_handshake_done(
+        exec_ctx, h,
+        grpc_set_tsi_error_result(
+            GRPC_ERROR_CREATE("Frame protector creation failed"), result));
     return;
   }
   h->secure_endpoint =
@@ -148,7 +168,7 @@
                                   h->left_overs.slices, h->left_overs.count);
   h->left_overs.count = 0;
   h->left_overs.length = 0;
-  security_handshake_done(exec_ctx, h, 1);
+  security_handshake_done(exec_ctx, h, GRPC_ERROR_NONE);
   return;
 }
 
@@ -157,9 +177,9 @@
   tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
 
   if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Peer extraction failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
+    security_handshake_done(
+        exec_ctx, h, grpc_set_tsi_error_result(
+                         GRPC_ERROR_CREATE("Peer extraction failed"), result));
     return;
   }
   grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
@@ -185,9 +205,9 @@
   } while (result == TSI_INCOMPLETE_DATA);
 
   if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshake failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
+    security_handshake_done(exec_ctx, h,
+                            grpc_set_tsi_error_result(
+                                GRPC_ERROR_CREATE("Handshake failed"), result));
     return;
   }
 
@@ -203,7 +223,7 @@
 
 static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
                                                  void *handshake,
-                                                 bool success) {
+                                                 grpc_error *error) {
   grpc_security_handshake *h = handshake;
   size_t consumed_slice_size = 0;
   tsi_result result = TSI_OK;
@@ -211,9 +231,10 @@
   size_t num_left_overs;
   int has_left_overs_in_current_slice = 0;
 
-  if (!success) {
-    gpr_log(GPR_ERROR, "Read failed.");
-    security_handshake_done(exec_ctx, h, 0);
+  if (error != GRPC_ERROR_NONE) {
+    security_handshake_done(
+        exec_ctx, h,
+        GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
     return;
   }
 
@@ -238,9 +259,9 @@
   }
 
   if (result != TSI_OK) {
-    gpr_log(GPR_ERROR, "Handshake failed with error %s",
-            tsi_result_to_string(result));
-    security_handshake_done(exec_ctx, h, 0);
+    security_handshake_done(exec_ctx, h,
+                            grpc_set_tsi_error_result(
+                                GRPC_ERROR_CREATE("Handshake failed"), result));
     return;
   }
 
@@ -270,13 +291,15 @@
 
 /* If handshake is NULL, the handshake is done. */
 static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
-                                           void *handshake, bool success) {
+                                           void *handshake, grpc_error *error) {
   grpc_security_handshake *h = handshake;
 
   /* Make sure that write is OK. */
-  if (!success) {
-    gpr_log(GPR_ERROR, "Write failed.");
-    if (handshake != NULL) security_handshake_done(exec_ctx, h, 0);
+  if (error != GRPC_ERROR_NONE) {
+    if (handshake != NULL)
+      security_handshake_done(
+          exec_ctx, h,
+          GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1));
     return;
   }
 
@@ -291,13 +314,19 @@
   }
 }
 
-void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
-                                tsi_handshaker *handshaker,
-                                grpc_security_connector *connector,
-                                bool is_client_side,
-                                grpc_endpoint *nonsecure_endpoint,
-                                grpc_security_handshake_done_cb cb,
-                                void *user_data) {
+static void on_timeout(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+  grpc_security_handshake *h = arg;
+  if (error == GRPC_ERROR_NONE) {
+    grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
+  }
+  unref_handshake(h);
+}
+
+void grpc_do_security_handshake(
+    grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
+    grpc_security_connector *connector, bool is_client_side,
+    grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+    grpc_security_handshake_done_cb cb, void *user_data) {
   grpc_security_connector_handshake_list *handshake_node;
   grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
   memset(h, 0, sizeof(grpc_security_handshake));
@@ -309,6 +338,7 @@
   h->wrapped_endpoint = nonsecure_endpoint;
   h->user_data = user_data;
   h->cb = cb;
+  gpr_ref_init(&h->refs, 2); /* timer and handshake proper each get a ref */
   grpc_closure_init(&h->on_handshake_data_sent_to_peer,
                     on_handshake_data_sent_to_peer, h);
   grpc_closure_init(&h->on_handshake_data_received_from_peer,
@@ -327,6 +357,8 @@
     gpr_mu_unlock(&server_connector->mu);
   }
   send_handshake_bytes_to_peer(exec_ctx, h);
+  grpc_timer_init(exec_ctx, &h->timer, deadline, on_timeout, h,
+                  gpr_now(deadline.clock_type));
 }
 
 void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/handshake.h
index 6ed850b..c0906dd 100644
--- a/src/core/lib/security/transport/handshake.h
+++ b/src/core/lib/security/transport/handshake.h
@@ -38,13 +38,11 @@
 #include "src/core/lib/security/transport/security_connector.h"
 
 /* Calls the callback upon completion. Takes owership of handshaker. */
-void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
-                                tsi_handshaker *handshaker,
-                                grpc_security_connector *connector,
-                                bool is_client_side,
-                                grpc_endpoint *nonsecure_endpoint,
-                                grpc_security_handshake_done_cb cb,
-                                void *user_data);
+void grpc_do_security_handshake(
+    grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
+    grpc_security_connector *connector, bool is_client_side,
+    grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+    grpc_security_handshake_done_cb cb, void *user_data);
 
 void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
 
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index 4438c8e..7650d68 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -38,6 +38,7 @@
 #include <grpc/support/slice_buffer.h>
 #include <grpc/support/sync.h>
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/security/transport/tsi_error.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/tsi/transport_security_interface.h"
 
@@ -126,8 +127,8 @@
 }
 
 static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
-                         bool success) {
-  if (grpc_trace_secure_endpoint) {
+                         grpc_error *error) {
+  if (false && grpc_trace_secure_endpoint) {
     size_t i;
     for (i = 0; i < ep->read_buffer->count; i++) {
       char *data = gpr_dump_slice(ep->read_buffer->slices[i],
@@ -137,11 +138,12 @@
     }
   }
   ep->read_buffer = NULL;
-  grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success, NULL);
+  grpc_exec_ctx_sched(exec_ctx, ep->read_cb, error, NULL);
   SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
 }
 
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
+                    grpc_error *error) {
   unsigned i;
   uint8_t keep_looping = 0;
   tsi_result result = TSI_OK;
@@ -149,9 +151,10 @@
   uint8_t *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
   uint8_t *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     gpr_slice_buffer_reset_and_unref(ep->read_buffer);
-    call_read_cb(exec_ctx, ep, 0);
+    call_read_cb(exec_ctx, ep, GRPC_ERROR_CREATE_REFERENCING(
+                                   "Secure read failed", &error, 1));
     return;
   }
 
@@ -208,11 +211,12 @@
 
   if (result != TSI_OK) {
     gpr_slice_buffer_reset_and_unref(ep->read_buffer);
-    call_read_cb(exec_ctx, ep, 0);
+    call_read_cb(exec_ctx, ep, grpc_set_tsi_error_result(
+                                   GRPC_ERROR_CREATE("Unwrap failed"), result));
     return;
   }
 
-  call_read_cb(exec_ctx, ep, 1);
+  call_read_cb(exec_ctx, ep, GRPC_ERROR_NONE);
 }
 
 static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
@@ -226,7 +230,7 @@
   if (ep->leftover_bytes.count) {
     gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
     GPR_ASSERT(ep->leftover_bytes.count == 0);
-    on_read(exec_ctx, ep, 1);
+    on_read(exec_ctx, ep, GRPC_ERROR_NONE);
     return;
   }
 
@@ -252,7 +256,7 @@
 
   gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
 
-  if (grpc_trace_secure_endpoint) {
+  if (false && grpc_trace_secure_endpoint) {
     for (i = 0; i < slices->count; i++) {
       char *data =
           gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -315,7 +319,10 @@
   if (result != TSI_OK) {
     /* TODO(yangg) do different things according to the error type? */
     gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    grpc_exec_ctx_sched(
+        exec_ctx, cb,
+        grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result),
+        NULL);
     return;
   }
 
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 72173e7..f0ee677 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -43,12 +43,12 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/alpn/alpn.h"
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/security/transport/handshake.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/tsi/fake_transport_security.h"
 #include "src/core/lib/tsi/ssl_transport_security.h"
@@ -127,23 +127,25 @@
 
 void grpc_channel_security_connector_do_handshake(
     grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
-    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
-    void *user_data) {
+    grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+    grpc_security_handshake_done_cb cb, void *user_data) {
   if (sc == NULL || nonsecure_endpoint == NULL) {
     cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   } else {
-    sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
+    sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, deadline, cb, user_data);
   }
 }
 
 void grpc_server_security_connector_do_handshake(
     grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
     grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
-    grpc_security_handshake_done_cb cb, void *user_data) {
+    gpr_timespec deadline, grpc_security_handshake_done_cb cb,
+    void *user_data) {
   if (sc == NULL || nonsecure_endpoint == NULL) {
     cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   } else {
-    sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data);
+    sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, deadline, cb,
+                     user_data);
   }
 }
 
@@ -310,20 +312,23 @@
 static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
                                       grpc_channel_security_connector *sc,
                                       grpc_endpoint *nonsecure_endpoint,
+                                      gpr_timespec deadline,
                                       grpc_security_handshake_done_cb cb,
                                       void *user_data) {
   grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
-                             true, nonsecure_endpoint, cb, user_data);
+                             true, nonsecure_endpoint, deadline, cb, user_data);
 }
 
 static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
                                      grpc_server_security_connector *sc,
                                      grpc_tcp_server_acceptor *acceptor,
                                      grpc_endpoint *nonsecure_endpoint,
+                                     gpr_timespec deadline,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
   grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
-                             false, nonsecure_endpoint, cb, user_data);
+                             false, nonsecure_endpoint, deadline, cb,
+                             user_data);
 }
 
 static grpc_security_connector_vtable fake_channel_vtable = {
@@ -413,6 +418,7 @@
 static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
                                      grpc_channel_security_connector *sc,
                                      grpc_endpoint *nonsecure_endpoint,
+                                     gpr_timespec deadline,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
   grpc_ssl_channel_security_connector *c =
@@ -427,7 +433,7 @@
     cb(exec_ctx, user_data, status, NULL, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
-                               nonsecure_endpoint, cb, user_data);
+                               nonsecure_endpoint, deadline, cb, user_data);
   }
 }
 
@@ -435,6 +441,7 @@
                                     grpc_server_security_connector *sc,
                                     grpc_tcp_server_acceptor *acceptor,
                                     grpc_endpoint *nonsecure_endpoint,
+                                    gpr_timespec deadline,
                                     grpc_security_handshake_done_cb cb,
                                     void *user_data) {
   grpc_ssl_server_security_connector *c =
@@ -446,7 +453,7 @@
     cb(exec_ctx, user_data, status, NULL, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
-                               nonsecure_endpoint, cb, user_data);
+                               nonsecure_endpoint, deadline, cb, user_data);
   }
 }
 
@@ -635,7 +642,8 @@
   char *default_root_certs_path =
       gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
   if (default_root_certs_path != NULL) {
-    result = gpr_load_file(default_root_certs_path, 0, NULL);
+    GRPC_LOG_IF_ERROR("load_file",
+                      grpc_load_file(default_root_certs_path, 0, &result));
     gpr_free(default_root_certs_path);
   }
 
@@ -653,7 +661,8 @@
   /* Fall back to installed certs if needed. */
   if (GPR_SLICE_IS_EMPTY(result) &&
       ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
-    result = gpr_load_file(installed_roots_path, 0, NULL);
+    GRPC_LOG_IF_ERROR("load_file",
+                      grpc_load_file(installed_roots_path, 0, &result));
   }
   return result;
 }
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index 84e586d..c2ddf5e 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -143,7 +143,7 @@
                           grpc_security_call_host_check_cb cb, void *user_data);
   void (*do_handshake)(grpc_exec_ctx *exec_ctx,
                        grpc_channel_security_connector *sc,
-                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
                        grpc_security_handshake_done_cb cb, void *user_data);
 };
 
@@ -156,8 +156,8 @@
 /* Handshake. */
 void grpc_channel_security_connector_do_handshake(
     grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
-    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
-    void *user_data);
+    grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
+    grpc_security_handshake_done_cb cb, void *user_data);
 
 /* --- server_security_connector object. ---
 
@@ -174,14 +174,14 @@
   void (*do_handshake)(grpc_exec_ctx *exec_ctx,
                        grpc_server_security_connector *sc,
                        grpc_tcp_server_acceptor *acceptor,
-                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_endpoint *nonsecure_endpoint, gpr_timespec deadline,
                        grpc_security_handshake_done_cb cb, void *user_data);
 };
 
 void grpc_server_security_connector_do_handshake(
     grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
     grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
-    grpc_security_handshake_done_cb cb, void *user_data);
+    gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
 
 void grpc_server_security_connector_shutdown(
     grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index b36be12..12e789b 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -128,7 +128,7 @@
     grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md,
                                elem);
     grpc_metadata_array_destroy(&calld->md);
-    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1);
+    grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE, NULL);
   } else {
     gpr_slice message;
     grpc_transport_stream_op close_op;
@@ -146,18 +146,21 @@
     calld->transport_op.send_trailing_metadata = NULL;
     grpc_transport_stream_op_add_close(&close_op, status, &message);
     grpc_call_next_op(&exec_ctx, elem, &close_op);
-    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0);
+    grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv,
+                        grpc_error_set_int(GRPC_ERROR_CREATE(error_details),
+                                           GRPC_ERROR_INT_GRPC_STATUS, status),
+                        NULL);
   }
 
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
-                         bool success) {
+                         grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     if (chand->creds->processor.process != NULL) {
       calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata);
       chand->creds->processor.process(
@@ -166,7 +169,8 @@
       return;
     }
   }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
+  grpc_exec_ctx_sched(exec_ctx, calld->on_done_recv, GRPC_ERROR_REF(error),
+                      NULL);
 }
 
 static void set_recv_ops_md_callbacks(grpc_call_element *elem,
diff --git a/test/core/http/fuzzer.c b/src/core/lib/security/transport/tsi_error.c
similarity index 74%
copy from test/core/http/fuzzer.c
copy to src/core/lib/security/transport/tsi_error.c
index c3c634f..afc1733 100644
--- a/test/core/http/fuzzer.c
+++ b/src/core/lib/security/transport/tsi_error.c
@@ -31,24 +31,10 @@
  *
  */
 
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
+#include "src/core/lib/security/transport/tsi_error.h"
 
-#include <grpc/support/alloc.h>
-
-#include "src/core/lib/http/parser.h"
-
-bool squelch = true;
-bool leak_check = true;
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_http_parser parser;
-  grpc_http_parser_init(&parser);
-  gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
-  grpc_http_parser_parse(&parser, slice);
-  grpc_http_parser_eof(&parser);
-  gpr_slice_unref(slice);
-  grpc_http_parser_destroy(&parser);
-  return 0;
+grpc_error *grpc_set_tsi_error_result(grpc_error *error, tsi_result result) {
+  return grpc_error_set_int(grpc_error_set_str(error, GRPC_ERROR_STR_TSI_ERROR,
+                                               tsi_result_to_string(result)),
+                            GRPC_ERROR_INT_TSI_CODE, result);
 }
diff --git a/test/core/http/fuzzer.c b/src/core/lib/security/transport/tsi_error.h
similarity index 74%
copy from test/core/http/fuzzer.c
copy to src/core/lib/security/transport/tsi_error.h
index c3c634f..636fbb8 100644
--- a/test/core/http/fuzzer.c
+++ b/src/core/lib/security/transport/tsi_error.h
@@ -31,24 +31,12 @@
  *
  */
 
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
+#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H
 
-#include <grpc/support/alloc.h>
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/tsi/transport_security_interface.h"
 
-#include "src/core/lib/http/parser.h"
+grpc_error *grpc_set_tsi_error_result(grpc_error *error, tsi_result result);
 
-bool squelch = true;
-bool leak_check = true;
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_http_parser parser;
-  grpc_http_parser_init(&parser);
-  gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
-  grpc_http_parser_parse(&parser, slice);
-  grpc_http_parser_eof(&parser);
-  gpr_slice_unref(slice);
-  grpc_http_parser_destroy(&parser);
-  return 0;
-}
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H */
diff --git a/src/core/lib/support/avl.c b/src/core/lib/support/avl.c
index 8d3ce23..acf8fd5 100644
--- a/src/core/lib/support/avl.c
+++ b/src/core/lib/support/avl.c
@@ -124,6 +124,15 @@
   return node ? node->value : NULL;
 }
 
+int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value) {
+  gpr_avl_node *node = get(avl.vtable, avl.root, key);
+  if (node != NULL) {
+    *value = node->value;
+    return 1;
+  }
+  return 0;
+}
+
 static gpr_avl_node *rotate_left(const gpr_avl_vtable *vtable, void *key,
                                  void *value, gpr_avl_node *left,
                                  gpr_avl_node *right) {
@@ -286,3 +295,5 @@
 }
 
 void gpr_avl_unref(gpr_avl avl) { unref_node(avl.vtable, avl.root); }
+
+int gpr_avl_is_empty(gpr_avl avl) { return avl.root == NULL; }
diff --git a/src/core/lib/surface/alarm.c b/src/core/lib/surface/alarm.c
index 2cf2f00..aa9d60e 100644
--- a/src/core/lib/surface/alarm.c
+++ b/src/core/lib/surface/alarm.c
@@ -48,9 +48,9 @@
 static void do_nothing_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
                                       grpc_cq_completion *c) {}
 
-static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_alarm *alarm = arg;
-  grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, success,
+  grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, error,
                  do_nothing_end_completion, NULL, &alarm->completion);
 }
 
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index c613f32..04291b0 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -100,6 +100,7 @@
   grpc_closure finish_batch;
   void *notify_tag;
   gpr_refcount steps_to_complete;
+  grpc_error *error;
 
   uint8_t send_initial_metadata;
   uint8_t send_message;
@@ -108,7 +109,6 @@
   uint8_t recv_message;
   uint8_t recv_final_op;
   uint8_t is_notify_tag_closure;
-  uint8_t success;
 } batch_control;
 
 struct grpc_call {
@@ -221,9 +221,9 @@
                                          grpc_status_code status,
                                          const char *description);
 static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
-                         bool success);
+                         grpc_error *error);
 static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                  bool success);
+                                  grpc_error *error);
 
 grpc_call *grpc_call_create(
     grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
@@ -360,7 +360,8 @@
   GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
 }
 
-static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, bool success) {
+static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
+                         grpc_error *error) {
   size_t i;
   int ii;
   grpc_call *c = call;
@@ -746,22 +747,23 @@
   enum { TC_CANCEL, TC_CLOSE } type;
 } termination_closure;
 
-static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, bool success) {
+static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
+                             grpc_error *error) {
   termination_closure *tc = tcp;
-  if (tc->type == TC_CANCEL) {
-    GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "cancel");
-  }
-  if (tc->type == TC_CLOSE) {
-    GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "close");
+  switch (tc->type) {
+    case TC_CANCEL:
+      GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "cancel");
+      break;
+    case TC_CLOSE:
+      GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "close");
+      break;
   }
   gpr_slice_unref(tc->optional_message);
-  if (tc->op_closure != NULL) {
-    grpc_exec_ctx_enqueue(exec_ctx, tc->op_closure, true, NULL);
-  }
+  grpc_exec_ctx_sched(exec_ctx, tc->op_closure, GRPC_ERROR_NONE, NULL);
   gpr_free(tc);
 }
 
-static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, bool success) {
+static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
   grpc_transport_stream_op op;
   termination_closure *tc = tcp;
   memset(&op, 0, sizeof(op));
@@ -772,7 +774,7 @@
   execute_op(exec_ctx, tc->call, &op);
 }
 
-static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, bool success) {
+static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
   grpc_transport_stream_op op;
   termination_closure *tc = tcp;
   memset(&op, 0, sizeof(op));
@@ -803,7 +805,7 @@
     grpc_closure_init(&tc->closure, send_close, tc);
     GRPC_CALL_INTERNAL_REF(tc->call, "close");
   }
-  grpc_exec_ctx_enqueue(exec_ctx, &tc->closure, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, &tc->closure, GRPC_ERROR_NONE, NULL);
   return GRPC_CALL_OK;
 }
 
@@ -866,11 +868,11 @@
   return CALL_FROM_TOP_ELEM(elem);
 }
 
-static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_call *call = arg;
   gpr_mu_lock(&call->mu);
   call->have_alarm = 0;
-  if (success) {
+  if (error != GRPC_ERROR_CANCELLED) {
     cancel_with_status(exec_ctx, call, GRPC_STATUS_DEADLINE_EXCEEDED,
                        "Deadline Exceeded");
   }
@@ -1056,7 +1058,8 @@
                                   batch_control *bctl) {
   grpc_call *call = bctl->call;
   if (bctl->is_notify_tag_closure) {
-    grpc_exec_ctx_enqueue(exec_ctx, bctl->notify_tag, bctl->success, NULL);
+    /* unrefs bctl->error */
+    grpc_exec_ctx_sched(exec_ctx, bctl->notify_tag, bctl->error, NULL);
     gpr_mu_lock(&call->mu);
     bctl->call->used_batches =
         (uint8_t)(bctl->call->used_batches &
@@ -1064,7 +1067,8 @@
     gpr_mu_unlock(&call->mu);
     GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
   } else {
-    grpc_cq_end_op(exec_ctx, bctl->call->cq, bctl->notify_tag, bctl->success,
+    /* unrefs bctl->error */
+    grpc_cq_end_op(exec_ctx, bctl->call->cq, bctl->notify_tag, bctl->error,
                    finish_batch_completion, bctl, &bctl->cq_completion);
   }
 }
@@ -1096,15 +1100,18 @@
 }
 
 static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                  bool success) {
+                                  grpc_error *error) {
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
 
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
                          call->receiving_slice);
     continue_receiving_slices(exec_ctx, bctl);
   } else {
+    if (grpc_trace_operation_failures) {
+      GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error));
+    }
     grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
     call->receiving_stream = NULL;
     grpc_byte_buffer_destroy(*call->receiving_buffer);
@@ -1153,15 +1160,15 @@
 }
 
 static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
-                                   bool success) {
+                                   grpc_error *error) {
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
 
   gpr_mu_lock(&bctl->call->mu);
-  if (bctl->call->has_initial_md_been_received || !success ||
+  if (bctl->call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
       call->receiving_stream == NULL) {
     gpr_mu_unlock(&bctl->call->mu);
-    process_data_after_md(exec_ctx, bctlp, success);
+    process_data_after_md(exec_ctx, bctlp, error);
   } else {
     call->saved_receiving_stream_ready_bctlp = bctlp;
     gpr_mu_unlock(&bctl->call->mu);
@@ -1219,14 +1226,14 @@
 }
 
 static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
-                                             void *bctlp, bool success) {
+                                             void *bctlp, grpc_error *error) {
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
 
   gpr_mu_lock(&call->mu);
 
-  if (!success) {
-    bctl->success = false;
+  if (error != GRPC_ERROR_NONE) {
+    bctl->error = GRPC_ERROR_REF(error);
   } else {
     grpc_metadata_batch *md =
         &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
@@ -1250,7 +1257,7 @@
     grpc_closure *saved_rsr_closure = grpc_closure_create(
         receiving_stream_ready, call->saved_receiving_stream_ready_bctlp);
     call->saved_receiving_stream_ready_bctlp = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, saved_rsr_closure, success, NULL);
+    grpc_exec_ctx_sched(exec_ctx, saved_rsr_closure, error, NULL);
   }
 
   gpr_mu_unlock(&call->mu);
@@ -1260,15 +1267,18 @@
   }
 }
 
-static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) {
+static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
+                         grpc_error *error) {
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
   grpc_call *child_call;
   grpc_call *next_child_call;
 
+  GRPC_ERROR_REF(error);
+
   gpr_mu_lock(&call->mu);
   if (bctl->send_initial_metadata) {
-    if (!success) {
+    if (error != GRPC_ERROR_NONE) {
       set_status_code(call, STATUS_FROM_CORE, GRPC_STATUS_UNAVAILABLE);
     }
     grpc_metadata_batch_destroy(
@@ -1314,13 +1324,17 @@
                        call->final_op.server.cancelled);
     }
 
-    success = 1;
+    GRPC_ERROR_UNREF(error);
+    error = GRPC_ERROR_NONE;
   }
-  bctl->success = success != 0;
+  GRPC_ERROR_UNREF(bctl->error);
+  bctl->error = GRPC_ERROR_REF(error);
   gpr_mu_unlock(&call->mu);
   if (gpr_unref(&bctl->steps_to_complete)) {
     post_batch_completion(exec_ctx, bctl);
   }
+
+  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
@@ -1350,7 +1364,7 @@
 
   if (nops == 0) {
     GRPC_CALL_INTERNAL_REF(call, "completion");
-    bctl->success = 1;
+    bctl->error = GRPC_ERROR_NONE;
     if (!is_notify_tag_closure) {
       grpc_cq_begin_op(call->cq, notify_tag);
     }
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
index f0b3c2e..8936e71 100644
--- a/src/core/lib/surface/channel.c
+++ b/src/core/lib/surface/channel.c
@@ -83,7 +83,8 @@
 /* the protobuf library will (by default) start warning at 100megs */
 #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
 
-static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, bool success);
+static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error);
 
 grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
                                   const grpc_channel_args *input_args,
@@ -310,7 +311,7 @@
 }
 
 static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
-                            bool iomgr_success) {
+                            grpc_error *error) {
   grpc_channel *channel = arg;
   grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
   while (channel->registered_calls) {
@@ -336,7 +337,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
   memset(&op, 0, sizeof(op));
-  op.disconnect = 1;
+  op.disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed");
   elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
   elem->filter->start_transport_op(&exec_ctx, elem, &op);
 
diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c
index 5a50698..9818f9d 100644
--- a/src/core/lib/surface/channel_ping.c
+++ b/src/core/lib/surface/channel_ping.c
@@ -53,10 +53,10 @@
   gpr_free(arg);
 }
 
-static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   ping_result *pr = arg;
-  grpc_cq_end_op(exec_ctx, pr->cq, pr->tag, success, ping_destroy, pr,
-                 &pr->completion_storage);
+  grpc_cq_end_op(exec_ctx, pr->cq, pr->tag, GRPC_ERROR_REF(error), ping_destroy,
+                 pr, &pr->completion_storage);
 }
 
 void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq,
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index 5eb7cf1..2cc6aa7 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -50,6 +50,8 @@
 #include "src/core/lib/surface/event_string.h"
 #include "src/core/lib/surface/surface_trace.h"
 
+int grpc_trace_operation_failures;
+
 typedef struct {
   grpc_pollset_worker **worker;
   void *tag;
@@ -92,7 +94,7 @@
 static grpc_completion_queue *g_freelist;
 
 static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
-                                     bool success);
+                                     grpc_error *error);
 
 void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); }
 
@@ -176,7 +178,7 @@
 }
 
 static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg,
-                                     bool success) {
+                                     grpc_error *error) {
   grpc_completion_queue *cc = arg;
   GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
 }
@@ -219,7 +221,7 @@
    event, then enter shutdown mode */
 /* Queue a GRPC_OP_COMPLETED operation */
 void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
-                    void *tag, int success,
+                    void *tag, grpc_error *error,
                     void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
                                  grpc_cq_completion *storage),
                     void *done_arg, grpc_cq_completion *storage) {
@@ -231,16 +233,24 @@
 #endif
 
   GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
-  GRPC_API_TRACE(
-      "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, success=%d, done=%p, "
-      "done_arg=%p, storage=%p)",
-      7, (exec_ctx, cc, tag, success, done, done_arg, storage));
+  if (grpc_api_trace ||
+      (grpc_trace_operation_failures && error != GRPC_ERROR_NONE)) {
+    const char *errmsg = grpc_error_string(error);
+    GRPC_API_TRACE(
+        "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, error=%s, done=%p, "
+        "done_arg=%p, storage=%p)",
+        7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage));
+    if (grpc_trace_operation_failures) {
+      gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg);
+    }
+    grpc_error_free_string(errmsg);
+  }
 
   storage->tag = tag;
   storage->done = done;
   storage->done_arg = done_arg;
-  storage->next =
-      ((uintptr_t)&cc->completed_head) | ((uintptr_t)(success != 0));
+  storage->next = ((uintptr_t)&cc->completed_head) |
+                  ((uintptr_t)(error == GRPC_ERROR_NONE));
 
   gpr_mu_lock(cc->mu);
 #ifndef NDEBUG
@@ -267,8 +277,15 @@
         break;
       }
     }
-    grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
+    grpc_error *kick_error =
+        grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
     gpr_mu_unlock(cc->mu);
+    if (kick_error != GRPC_ERROR_NONE) {
+      const char *msg = grpc_error_string(kick_error);
+      gpr_log(GPR_ERROR, "Kick failed: %s", msg);
+      grpc_error_free_string(msg);
+      GRPC_ERROR_UNREF(kick_error);
+    }
   } else {
     cc->completed_tail->next =
         ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
@@ -282,6 +299,8 @@
   }
 
   GPR_TIMER_END("grpc_cq_end_op", 0);
+
+  GRPC_ERROR_UNREF(error);
 }
 
 grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
@@ -347,8 +366,18 @@
       gpr_mu_lock(cc->mu);
       continue;
     } else {
-      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
-                        iteration_deadline);
+      grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc),
+                                          &worker, now, iteration_deadline);
+      if (err != GRPC_ERROR_NONE) {
+        gpr_mu_unlock(cc->mu);
+        const char *msg = grpc_error_string(err);
+        gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
+        grpc_error_free_string(msg);
+        GRPC_ERROR_UNREF(err);
+        memset(&ret, 0, sizeof(ret));
+        ret.type = GRPC_QUEUE_TIMEOUT;
+        break;
+      }
     }
   }
   GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
@@ -464,8 +493,19 @@
       grpc_exec_ctx_flush(&exec_ctx);
       gpr_mu_lock(cc->mu);
     } else {
-      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
-                        iteration_deadline);
+      grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc),
+                                          &worker, now, iteration_deadline);
+      if (err != GRPC_ERROR_NONE) {
+        del_plucker(cc, tag, &worker);
+        gpr_mu_unlock(cc->mu);
+        const char *msg = grpc_error_string(err);
+        gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
+        grpc_error_free_string(msg);
+        GRPC_ERROR_UNREF(err);
+        memset(&ret, 0, sizeof(ret));
+        ret.type = GRPC_QUEUE_TIMEOUT;
+        break;
+      }
     }
     del_plucker(cc, tag, &worker);
   }
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index 3d0dd13..b9dd109 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -39,6 +39,8 @@
 #include <grpc/grpc.h>
 #include "src/core/lib/iomgr/pollset.h"
 
+extern int grpc_trace_operation_failures;
+
 typedef struct grpc_cq_completion {
   /** user supplied tag */
   void *tag;
@@ -75,7 +77,7 @@
 /* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to
    grpc_cq_begin_op */
 void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
-                    void *tag, int success,
+                    void *tag, grpc_error *error,
                     void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
                                  grpc_cq_completion *storage),
                     void *done_arg, grpc_cq_completion *storage);
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index 1c8b709..f07039c 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -165,6 +165,7 @@
                          &grpc_trace_channel_stack_builder);
     grpc_register_tracer("http1", &grpc_http1_trace);
     grpc_register_tracer("compression", &grpc_compression_trace);
+    grpc_register_tracer("op_failure", &grpc_trace_operation_failures);
     grpc_security_pre_init();
     grpc_iomgr_init();
     grpc_executor_init();
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index 8223555..5ea4cba 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -80,7 +80,8 @@
   } else if (op->recv_trailing_metadata != NULL) {
     fill_metadata(elem, op->recv_trailing_metadata);
   }
-  grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
+  grpc_transport_stream_op_finish_with_failure(
+      exec_ctx, op, GRPC_ERROR_CREATE("lame client channel"));
 }
 
 static char *lame_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
@@ -93,15 +94,17 @@
   if (op->on_connectivity_state_change) {
     GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_SHUTDOWN);
     *op->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
-    op->on_connectivity_state_change->cb(
-        exec_ctx, op->on_connectivity_state_change->cb_arg, 1);
+    grpc_exec_ctx_sched(exec_ctx, op->on_connectivity_state_change,
+                        GRPC_ERROR_NONE, NULL);
   }
   if (op->on_consumed != NULL) {
-    op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 1);
+    grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
   }
   if (op->send_ping != NULL) {
-    op->send_ping->cb(exec_ctx, op->send_ping->cb_arg, 0);
+    grpc_exec_ctx_sched(exec_ctx, op->send_ping,
+                        GRPC_ERROR_CREATE("lame client channel"), NULL);
   }
+  GRPC_ERROR_UNREF(op->disconnect_with_error);
 }
 
 static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 88d898b..def6e50 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -230,9 +230,10 @@
 #define SERVER_FROM_CALL_ELEM(elem) \
   (((channel_data *)(elem)->channel_data)->server)
 
-static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, bool success);
+static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld,
+                            grpc_error *error);
 static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      size_t cq_idx, requested_call *rc);
+                      size_t cq_idx, requested_call *rc, grpc_error *error);
 /* Before calling maybe_finish_shutdown, we must hold mu_global and not
    hold mu_call */
 static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_server *server);
@@ -263,14 +264,14 @@
 };
 
 static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
-                             bool iomgr_status_ignored) {
+                             grpc_error *error) {
   struct shutdown_cleanup_args *a = arg;
   gpr_slice_unref(a->slice);
   gpr_free(a);
 }
 
 static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
-                          int send_goaway, int send_disconnect) {
+                          int send_goaway, grpc_error *send_disconnect) {
   grpc_transport_op op;
   struct shutdown_cleanup_args *sc;
   grpc_channel_element *elem;
@@ -281,7 +282,7 @@
   sc->slice = gpr_slice_from_copied_string("Server shutdown");
   op.goaway_message = &sc->slice;
   op.goaway_status = GRPC_STATUS_OK;
-  op.disconnect = send_disconnect;
+  op.disconnect_with_error = send_disconnect;
   grpc_closure_init(&sc->closure, shutdown_cleanup, sc);
   op.on_consumed = &sc->closure;
 
@@ -292,14 +293,16 @@
 static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
                                          channel_broadcaster *cb,
                                          int send_goaway,
-                                         int force_disconnect) {
+                                         grpc_error *force_disconnect) {
   size_t i;
 
   for (i = 0; i < cb->num_channels; i++) {
-    send_shutdown(exec_ctx, cb->channels[i], send_goaway, force_disconnect);
+    send_shutdown(exec_ctx, cb->channels[i], send_goaway,
+                  GRPC_ERROR_REF(force_disconnect));
     GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, cb->channels[i], "broadcast");
   }
   gpr_free(cb->channels);
+  GRPC_ERROR_UNREF(force_disconnect);
 }
 
 /*
@@ -325,7 +328,8 @@
   gpr_free(rm->requests_per_cq);
 }
 
-static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem, bool success) {
+static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem,
+                        grpc_error *error) {
   grpc_call_destroy(grpc_call_from_top_element(elem));
 }
 
@@ -340,20 +344,24 @@
     grpc_closure_init(
         &calld->kill_zombie_closure, kill_zombie,
         grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
-    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE,
+                        NULL);
   }
 }
 
 static void request_matcher_kill_requests(grpc_exec_ctx *exec_ctx,
                                           grpc_server *server,
-                                          request_matcher *rm) {
+                                          request_matcher *rm,
+                                          grpc_error *error) {
   int request_id;
   for (size_t i = 0; i < server->cq_count; i++) {
     while ((request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[i])) !=
            -1) {
-      fail_call(exec_ctx, server, i, &server->requested_calls[request_id]);
+      fail_call(exec_ctx, server, i, &server->requested_calls[request_id],
+                GRPC_ERROR_REF(error));
     }
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 /*
@@ -410,7 +418,7 @@
 }
 
 static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd,
-                                   bool success) {
+                                   grpc_error *error) {
   channel_data *chand = cd;
   grpc_server *server = chand->server;
   GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "server");
@@ -499,25 +507,26 @@
       grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
   channel_data *chand = elem->channel_data;
   server_ref(chand->server);
-  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, true, done_request_event, rc,
-                 &rc->completion);
+  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, GRPC_ERROR_NONE,
+                 done_request_event, rc, &rc->completion);
 }
 
-static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error) {
   grpc_call_element *call_elem = arg;
   call_data *calld = call_elem->call_data;
   channel_data *chand = call_elem->channel_data;
   request_matcher *rm = calld->request_matcher;
   grpc_server *server = rm->server;
 
-  if (!success || gpr_atm_acq_load(&server->shutdown_flag)) {
+  if (error != GRPC_ERROR_NONE || gpr_atm_acq_load(&server->shutdown_flag)) {
     gpr_mu_lock(&calld->mu_state);
     calld->state = ZOMBIED;
     gpr_mu_unlock(&calld->mu_state);
     grpc_closure_init(
         &calld->kill_zombie_closure, kill_zombie,
         grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
-    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure, error, NULL);
     return;
   }
 
@@ -562,7 +571,8 @@
     calld->state = ZOMBIED;
     gpr_mu_unlock(&calld->mu_state);
     grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
-    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE,
+                        NULL);
     return;
   }
 
@@ -570,7 +580,7 @@
 
   switch (payload_handling) {
     case GRPC_SRM_PAYLOAD_NONE:
-      publish_new_rpc(exec_ctx, elem, true);
+      publish_new_rpc(exec_ctx, elem, GRPC_ERROR_NONE);
       break;
     case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
       grpc_op op;
@@ -658,18 +668,21 @@
 }
 
 static void kill_pending_work_locked(grpc_exec_ctx *exec_ctx,
-                                     grpc_server *server) {
+                                     grpc_server *server, grpc_error *error) {
   if (server->started) {
     request_matcher_kill_requests(exec_ctx, server,
-                                  &server->unregistered_request_matcher);
+                                  &server->unregistered_request_matcher,
+                                  GRPC_ERROR_REF(error));
     request_matcher_zombify_all_pending_calls(
         exec_ctx, &server->unregistered_request_matcher);
     for (registered_method *rm = server->registered_methods; rm;
          rm = rm->next) {
-      request_matcher_kill_requests(exec_ctx, server, &rm->request_matcher);
+      request_matcher_kill_requests(exec_ctx, server, &rm->request_matcher,
+                                    GRPC_ERROR_REF(error));
       request_matcher_zombify_all_pending_calls(exec_ctx, &rm->request_matcher);
     }
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
@@ -679,7 +692,8 @@
     return;
   }
 
-  kill_pending_work_locked(exec_ctx, server);
+  kill_pending_work_locked(exec_ctx, server,
+                           GRPC_ERROR_CREATE("Server Shutdown"));
 
   if (server->root_channel_data.next != &server->root_channel_data ||
       server->listeners_destroyed < num_listeners(server)) {
@@ -700,7 +714,8 @@
   for (i = 0; i < server->num_shutdown_tags; i++) {
     server_ref(server);
     grpc_cq_end_op(exec_ctx, server->shutdown_tags[i].cq,
-                   server->shutdown_tags[i].tag, 1, done_shutdown_event, server,
+                   server->shutdown_tags[i].tag, GRPC_ERROR_NONE,
+                   done_shutdown_event, server,
                    &server->shutdown_tags[i].completion);
   }
 }
@@ -723,11 +738,12 @@
 }
 
 static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
-                                            bool success) {
+                                            grpc_error *error) {
   grpc_call_element *elem = ptr;
   call_data *calld = elem->call_data;
   gpr_timespec op_deadline;
 
+  GRPC_ERROR_REF(error);
   grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, elem);
   op_deadline = calld->recv_initial_metadata->deadline;
   if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
@@ -736,11 +752,13 @@
   if (calld->host && calld->path) {
     /* do nothing */
   } else {
-    success = 0;
+    GRPC_ERROR_UNREF(error);
+    error =
+        GRPC_ERROR_CREATE_REFERENCING("Missing :authority or :path", &error, 1);
   }
 
-  calld->on_done_recv_initial_metadata->cb(
-      exec_ctx, calld->on_done_recv_initial_metadata->cb_arg, success);
+  grpc_exec_ctx_sched(exec_ctx, calld->on_done_recv_initial_metadata, error,
+                      NULL);
 }
 
 static void server_mutate_op(grpc_call_element *elem,
@@ -765,10 +783,10 @@
 }
 
 static void got_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
-                                 bool success) {
+                                 grpc_error *error) {
   grpc_call_element *elem = ptr;
   call_data *calld = elem->call_data;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     start_new_rpc(exec_ctx, elem);
   } else {
     gpr_mu_lock(&calld->mu_state);
@@ -776,7 +794,8 @@
       calld->state = ZOMBIED;
       gpr_mu_unlock(&calld->mu_state);
       grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
-      grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure,
+                          GRPC_ERROR_NONE, NULL);
     } else if (calld->state == PENDING) {
       calld->state = ZOMBIED;
       gpr_mu_unlock(&calld->mu_state);
@@ -809,7 +828,7 @@
 }
 
 static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
-                                         bool iomgr_status_ignored) {
+                                         grpc_error *error) {
   channel_data *chand = cd;
   grpc_server *server = chand->server;
   if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
@@ -1148,7 +1167,9 @@
   op.set_accept_stream_user_data = chand;
   op.on_connectivity_state_change = &chand->channel_connectivity_changed;
   op.connectivity_state = &chand->connectivity_state;
-  op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0;
+  if (gpr_atm_acq_load(&s->shutdown_flag) != 0) {
+    op.disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown");
+  }
   grpc_transport_perform_op(exec_ctx, transport, &op);
 }
 
@@ -1159,7 +1180,7 @@
 }
 
 static void listener_destroy_done(grpc_exec_ctx *exec_ctx, void *s,
-                                  bool success) {
+                                  grpc_error *error) {
   grpc_server *server = s;
   gpr_mu_lock(&server->mu_global);
   server->listeners_destroyed++;
@@ -1181,8 +1202,8 @@
   gpr_mu_lock(&server->mu_global);
   grpc_cq_begin_op(cq, tag);
   if (server->shutdown_published) {
-    grpc_cq_end_op(&exec_ctx, cq, tag, 1, done_published_shutdown, NULL,
-                   gpr_malloc(sizeof(grpc_cq_completion)));
+    grpc_cq_end_op(&exec_ctx, cq, tag, GRPC_ERROR_NONE, done_published_shutdown,
+                   NULL, gpr_malloc(sizeof(grpc_cq_completion)));
     gpr_mu_unlock(&server->mu_global);
     goto done;
   }
@@ -1205,7 +1226,8 @@
 
   /* collect all unregistered then registered calls */
   gpr_mu_lock(&server->mu_call);
-  kill_pending_work_locked(&exec_ctx, server);
+  kill_pending_work_locked(&exec_ctx, server,
+                           GRPC_ERROR_CREATE("Server Shutdown"));
   gpr_mu_unlock(&server->mu_call);
 
   maybe_finish_shutdown(&exec_ctx, server);
@@ -1233,7 +1255,8 @@
   channel_broadcaster_init(server, &broadcaster);
   gpr_mu_unlock(&server->mu_global);
 
-  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0, 1);
+  channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0,
+                               GRPC_ERROR_CREATE("Cancelling all calls"));
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -1280,13 +1303,15 @@
   request_matcher *rm = NULL;
   int request_id;
   if (gpr_atm_acq_load(&server->shutdown_flag)) {
-    fail_call(exec_ctx, server, cq_idx, rc);
+    fail_call(exec_ctx, server, cq_idx, rc,
+              GRPC_ERROR_CREATE("Server Shutdown"));
     return GRPC_CALL_OK;
   }
   request_id = gpr_stack_lockfree_pop(server->request_freelist);
   if (request_id == -1) {
     /* out of request ids: just fail this one */
-    fail_call(exec_ctx, server, cq_idx, rc);
+    fail_call(exec_ctx, server, cq_idx, rc,
+              GRPC_ERROR_CREATE("Server Shutdown"));
     return GRPC_CALL_OK;
   }
   switch (rc->type) {
@@ -1314,8 +1339,8 @@
         grpc_closure_init(
             &calld->kill_zombie_closure, kill_zombie,
             grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
-        grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true,
-                              NULL);
+        grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure,
+                            GRPC_ERROR_NONE, NULL);
       } else {
         GPR_ASSERT(calld->state == PENDING);
         calld->state = ACTIVATED;
@@ -1421,13 +1446,14 @@
 }
 
 static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
-                      size_t cq_idx, requested_call *rc) {
+                      size_t cq_idx, requested_call *rc, grpc_error *error) {
   *rc->call = NULL;
   rc->initial_metadata->count = 0;
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
 
   server_ref(server);
-  grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, 0, done_request_event,
-                 rc, &rc->completion);
+  grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, error,
+                 done_request_event, rc, &rc->completion);
 }
 
 const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
index 74a5ef5..054f112 100644
--- a/src/core/lib/transport/connectivity_state.c
+++ b/src/core/lib/transport/connectivity_state.c
@@ -52,7 +52,7 @@
     case GRPC_CHANNEL_TRANSIENT_FAILURE:
       return "TRANSIENT_FAILURE";
     case GRPC_CHANNEL_SHUTDOWN:
-      return "FATAL_FAILURE";
+      return "SHUTDOWN";
   }
   GPR_UNREACHABLE_CODE(return "UNKNOWN");
 }
@@ -61,35 +61,40 @@
                                   grpc_connectivity_state init_state,
                                   const char *name) {
   tracker->current_state = init_state;
+  tracker->current_error = GRPC_ERROR_NONE;
   tracker->watchers = NULL;
   tracker->name = gpr_strdup(name);
 }
 
 void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
                                      grpc_connectivity_state_tracker *tracker) {
-  int success;
+  grpc_error *error;
   grpc_connectivity_state_watcher *w;
   while ((w = tracker->watchers)) {
     tracker->watchers = w->next;
 
     if (GRPC_CHANNEL_SHUTDOWN != *w->current) {
       *w->current = GRPC_CHANNEL_SHUTDOWN;
-      success = 1;
+      error = GRPC_ERROR_NONE;
     } else {
-      success = 0;
+      error = GRPC_ERROR_CREATE("Shutdown connectivity owner");
     }
-    grpc_exec_ctx_enqueue(exec_ctx, w->notify, success, NULL);
+    grpc_exec_ctx_sched(exec_ctx, w->notify, error, NULL);
     gpr_free(w);
   }
+  GRPC_ERROR_UNREF(tracker->current_error);
   gpr_free(tracker->name);
 }
 
 grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker) {
+    grpc_connectivity_state_tracker *tracker, grpc_error **error) {
   if (grpc_connectivity_state_trace) {
     gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
             grpc_connectivity_state_name(tracker->current_state));
   }
+  if (error != NULL) {
+    *error = GRPC_ERROR_REF(tracker->current_error);
+  }
   return tracker->current_state;
 }
 
@@ -109,7 +114,7 @@
   if (current == NULL) {
     grpc_connectivity_state_watcher *w = tracker->watchers;
     if (w != NULL && w->notify == notify) {
-      grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
+      grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
       tracker->watchers = w->next;
       gpr_free(w);
       return 0;
@@ -117,7 +122,7 @@
     while (w != NULL) {
       grpc_connectivity_state_watcher *rm_candidate = w->next;
       if (rm_candidate != NULL && rm_candidate->notify == notify) {
-        grpc_exec_ctx_enqueue(exec_ctx, notify, false, NULL);
+        grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
         w->next = w->next->next;
         gpr_free(rm_candidate);
         return 0;
@@ -128,7 +133,8 @@
   } else {
     if (tracker->current_state != *current) {
       *current = tracker->current_state;
-      grpc_exec_ctx_enqueue(exec_ctx, notify, true, NULL);
+      grpc_exec_ctx_sched(exec_ctx, notify,
+                          GRPC_ERROR_REF(tracker->current_error), NULL);
     } else {
       grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
       w->current = current;
@@ -143,13 +149,28 @@
 void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
                                  grpc_connectivity_state_tracker *tracker,
                                  grpc_connectivity_state state,
-                                 const char *reason) {
+                                 grpc_error *error, const char *reason) {
   grpc_connectivity_state_watcher *w;
   if (grpc_connectivity_state_trace) {
-    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
-            grpc_connectivity_state_name(tracker->current_state),
-            grpc_connectivity_state_name(state), reason);
+    const char *error_string = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
+            tracker->name, grpc_connectivity_state_name(tracker->current_state),
+            grpc_connectivity_state_name(state), reason, error, error_string);
+    grpc_error_free_string(error_string);
   }
+  switch (state) {
+    case GRPC_CHANNEL_CONNECTING:
+    case GRPC_CHANNEL_IDLE:
+    case GRPC_CHANNEL_READY:
+      GPR_ASSERT(error == GRPC_ERROR_NONE);
+      break;
+    case GRPC_CHANNEL_SHUTDOWN:
+    case GRPC_CHANNEL_TRANSIENT_FAILURE:
+      GPR_ASSERT(error != GRPC_ERROR_NONE);
+      break;
+  }
+  GRPC_ERROR_UNREF(tracker->current_error);
+  tracker->current_error = error;
   if (tracker->current_state == state) {
     return;
   }
@@ -158,7 +179,8 @@
   while ((w = tracker->watchers) != NULL) {
     *w->current = tracker->current_state;
     tracker->watchers = w->next;
-    grpc_exec_ctx_enqueue(exec_ctx, w->notify, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, w->notify,
+                        GRPC_ERROR_REF(tracker->current_error), NULL);
     gpr_free(w);
   }
 }
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 2eb7e09..7a2fa52 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -49,6 +49,8 @@
 typedef struct {
   /** current connectivity state */
   grpc_connectivity_state current_state;
+  /** error associated with state */
+  grpc_error *current_error;
   /** all our watchers */
   grpc_connectivity_state_watcher *watchers;
   /** a name to help debugging */
@@ -70,10 +72,11 @@
 void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
                                  grpc_connectivity_state_tracker *tracker,
                                  grpc_connectivity_state state,
+                                 grpc_error *associated_error,
                                  const char *reason);
 
 grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker);
+    grpc_connectivity_state_tracker *tracker, grpc_error **current_error);
 
 /** Return 1 if the channel should start connecting, 0 otherwise.
     If current==NULL cancel notify if it is already queued (success==0 in that
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
index b65e157..1105494 100644
--- a/src/core/lib/transport/transport.c
+++ b/src/core/lib/transport/transport.c
@@ -60,7 +60,7 @@
                        grpc_stream_refcount *refcount) {
 #endif
   if (gpr_unref(&refcount->refs)) {
-    grpc_exec_ctx_enqueue(exec_ctx, &refcount->destroy, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE, NULL);
   }
 }
 
@@ -152,11 +152,14 @@
   return transport->vtable->get_peer(exec_ctx, transport);
 }
 
-void grpc_transport_stream_op_finish_with_failure(
-    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) {
-  grpc_exec_ctx_enqueue(exec_ctx, op->recv_message_ready, false, NULL);
-  grpc_exec_ctx_enqueue(exec_ctx, op->recv_initial_metadata_ready, false, NULL);
-  grpc_exec_ctx_enqueue(exec_ctx, op->on_complete, false, NULL);
+void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
+                                                  grpc_transport_stream_op *op,
+                                                  grpc_error *error) {
+  grpc_exec_ctx_sched(exec_ctx, op->recv_message_ready, GRPC_ERROR_REF(error),
+                      NULL);
+  grpc_exec_ctx_sched(exec_ctx, op->recv_initial_metadata_ready,
+                      GRPC_ERROR_REF(error), NULL);
+  grpc_exec_ctx_sched(exec_ctx, op->on_complete, error, NULL);
 }
 
 void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
@@ -180,11 +183,11 @@
   grpc_closure closure;
 } close_message_data;
 
-static void free_message(grpc_exec_ctx *exec_ctx, void *p, bool iomgr_success) {
+static void free_message(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
   close_message_data *cmd = p;
   gpr_slice_unref(cmd->message);
   if (cmd->then_call != NULL) {
-    cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, iomgr_success);
+    cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, GRPC_ERROR_REF(error));
   }
   gpr_free(cmd);
 }
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index ed06fc3..a46ccb6 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -155,7 +155,7 @@
   grpc_closure *on_connectivity_state_change;
   grpc_connectivity_state *connectivity_state;
   /** should the transport be disconnected */
-  int disconnect;
+  grpc_error *disconnect_with_error;
   /** should we send a goaway?
       after a goaway is sent, once there are no more active calls on
       the transport, the transport should disconnect */
@@ -216,7 +216,8 @@
                                    grpc_stream *stream, void *and_free_memory);
 
 void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
-                                                  grpc_transport_stream_op *op);
+                                                  grpc_transport_stream_op *op,
+                                                  grpc_error *error);
 
 void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
                                                grpc_status_code status);
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index d3e5ce0..0ba77a5 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -63,6 +63,7 @@
       call_(nullptr),
       call_canceled_(false),
       deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
+      census_context_(nullptr),
       propagate_from_call_(nullptr) {
   g_client_callbacks->DefaultConstructor(this);
 }
diff --git a/src/node/performance/benchmark_client.js b/src/node/performance/benchmark_client.js
index 262aa33..5ef5260 100644
--- a/src/node/performance/benchmark_client.js
+++ b/src/node/performance/benchmark_client.js
@@ -42,6 +42,8 @@
 var path = require('path');
 var util = require('util');
 var EventEmitter = require('events');
+
+var async = require('async');
 var _ = require('lodash');
 var PoissonProcess = require('poisson-process');
 var Histogram = require('./histogram');
@@ -128,6 +130,36 @@
 util.inherits(BenchmarkClient, EventEmitter);
 
 /**
+ * Start every client in the list of clients by waiting for each to be ready,
+ * then starting outstanding_rpcs_per_channel calls on each of them
+ * @param {Array<grpc.Client>} client_list The list of clients
+ * @param {Number} outstanding_rpcs_per_channel The number of calls to start
+ *     on each client
+ * @param {function(grpc.Client)} makeCall Function to make a single call on
+ *     a single client
+ * @param {EventEmitter} emitter The event emitter to send errors on, if
+ *     necessary
+ */
+function startAllClients(client_list, outstanding_rpcs_per_channel, makeCall,
+                         emitter) {
+  var ready_wait_funcs = _.map(client_list, function(client) {
+    return _.partial(grpc.waitForClientReady, client, Infinity);
+  });
+  async.parallel(ready_wait_funcs, function(err) {
+    if (err) {
+      emitter.emit('error', err);
+      return;
+    }
+
+    _.each(client_list, function(client) {
+      _.times(outstanding_rpcs_per_channel, function() {
+        makeCall(client);
+      });
+    });
+  });
+}
+
+/**
  * Start a closed-loop test. For each channel, start
  * outstanding_rpcs_per_channel RPCs. Then, whenever an RPC finishes, start
  * another one.
@@ -212,11 +244,7 @@
     };
   }
 
-  _.each(client_list, function(client) {
-    _.times(outstanding_rpcs_per_channel, function() {
-      makeCall(client);
-    });
-  });
+  startAllClients(client_list, outstanding_rpcs_per_channel, makeCall, self);
 };
 
 /**
@@ -310,14 +338,12 @@
 
   var averageIntervalMs = (1 / offered_load) * 1000;
 
-  _.each(client_list, function(client) {
-    _.times(outstanding_rpcs_per_channel, function() {
-      var p = PoissonProcess.create(averageIntervalMs, function() {
-        makeCall(client, p);
-      });
-      p.start();
+  startAllClients(client_list, outstanding_rpcs_per_channel, function(client){
+    var p = PoissonProcess.create(averageIntervalMs, function() {
+      makeCall(client, p);
     });
-  });
+    p.start();
+  }, self);
 };
 
 /**
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 5c49f6c..8437e74 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -260,6 +260,8 @@
 gpr_avl_add_type gpr_avl_add_import;
 gpr_avl_remove_type gpr_avl_remove_import;
 gpr_avl_get_type gpr_avl_get_import;
+gpr_avl_maybe_get_type gpr_avl_maybe_get_import;
+gpr_avl_is_empty_type gpr_avl_is_empty_import;
 gpr_cmdline_create_type gpr_cmdline_create_import;
 gpr_cmdline_add_int_type gpr_cmdline_add_int_import;
 gpr_cmdline_add_flag_type gpr_cmdline_add_flag_import;
@@ -533,6 +535,8 @@
   gpr_avl_add_import = (gpr_avl_add_type) GetProcAddress(library, "gpr_avl_add");
   gpr_avl_remove_import = (gpr_avl_remove_type) GetProcAddress(library, "gpr_avl_remove");
   gpr_avl_get_import = (gpr_avl_get_type) GetProcAddress(library, "gpr_avl_get");
+  gpr_avl_maybe_get_import = (gpr_avl_maybe_get_type) GetProcAddress(library, "gpr_avl_maybe_get");
+  gpr_avl_is_empty_import = (gpr_avl_is_empty_type) GetProcAddress(library, "gpr_avl_is_empty");
   gpr_cmdline_create_import = (gpr_cmdline_create_type) GetProcAddress(library, "gpr_cmdline_create");
   gpr_cmdline_add_int_import = (gpr_cmdline_add_int_type) GetProcAddress(library, "gpr_cmdline_add_int");
   gpr_cmdline_add_flag_import = (gpr_cmdline_add_flag_type) GetProcAddress(library, "gpr_cmdline_add_flag");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index 62865f8..d52e859 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -731,6 +731,12 @@
 typedef void *(*gpr_avl_get_type)(gpr_avl avl, void *key);
 extern gpr_avl_get_type gpr_avl_get_import;
 #define gpr_avl_get gpr_avl_get_import
+typedef int(*gpr_avl_maybe_get_type)(gpr_avl avl, void *key, void **value);
+extern gpr_avl_maybe_get_type gpr_avl_maybe_get_import;
+#define gpr_avl_maybe_get gpr_avl_maybe_get_import
+typedef int(*gpr_avl_is_empty_type)(gpr_avl avl);
+extern gpr_avl_is_empty_type gpr_avl_is_empty_import;
+#define gpr_avl_is_empty gpr_avl_is_empty_import
 typedef gpr_cmdline *(*gpr_cmdline_create_type)(const char *description);
 extern gpr_cmdline_create_type gpr_cmdline_create_import;
 #define gpr_cmdline_create gpr_cmdline_create_import
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 2a52294..839c555 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -45,7 +45,6 @@
   'src/core/lib/support/env_windows.c',
   'src/core/lib/support/histogram.c',
   'src/core/lib/support/host_port.c',
-  'src/core/lib/support/load_file.c',
   'src/core/lib/support/log.c',
   'src/core/lib/support/log_android.c',
   'src/core/lib/support/log_linux.c',
@@ -94,6 +93,7 @@
   'src/core/lib/iomgr/endpoint.c',
   'src/core/lib/iomgr/endpoint_pair_posix.c',
   'src/core/lib/iomgr/endpoint_pair_windows.c',
+  'src/core/lib/iomgr/error.c',
   'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
   'src/core/lib/iomgr/ev_poll_posix.c',
   'src/core/lib/iomgr/ev_posix.c',
@@ -103,6 +103,7 @@
   'src/core/lib/iomgr/iomgr.c',
   'src/core/lib/iomgr/iomgr_posix.c',
   'src/core/lib/iomgr/iomgr_windows.c',
+  'src/core/lib/iomgr/load_file.c',
   'src/core/lib/iomgr/polling_entity.c',
   'src/core/lib/iomgr/pollset_set_windows.c',
   'src/core/lib/iomgr/pollset_windows.c',
@@ -205,6 +206,7 @@
   'src/core/lib/security/transport/secure_endpoint.c',
   'src/core/lib/security/transport/security_connector.c',
   'src/core/lib/security/transport/server_auth_filter.c',
+  'src/core/lib/security/transport/tsi_error.c',
   'src/core/lib/security/util/b64.c',
   'src/core/lib/security/util/json_util.c',
   'src/core/lib/surface/init_secure.c',
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index c13d1a0..4d97076 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -260,6 +260,8 @@
 gpr_avl_add_type gpr_avl_add_import;
 gpr_avl_remove_type gpr_avl_remove_import;
 gpr_avl_get_type gpr_avl_get_import;
+gpr_avl_maybe_get_type gpr_avl_maybe_get_import;
+gpr_avl_is_empty_type gpr_avl_is_empty_import;
 gpr_cmdline_create_type gpr_cmdline_create_import;
 gpr_cmdline_add_int_type gpr_cmdline_add_int_import;
 gpr_cmdline_add_flag_type gpr_cmdline_add_flag_import;
@@ -529,6 +531,8 @@
   gpr_avl_add_import = (gpr_avl_add_type) GetProcAddress(library, "gpr_avl_add");
   gpr_avl_remove_import = (gpr_avl_remove_type) GetProcAddress(library, "gpr_avl_remove");
   gpr_avl_get_import = (gpr_avl_get_type) GetProcAddress(library, "gpr_avl_get");
+  gpr_avl_maybe_get_import = (gpr_avl_maybe_get_type) GetProcAddress(library, "gpr_avl_maybe_get");
+  gpr_avl_is_empty_import = (gpr_avl_is_empty_type) GetProcAddress(library, "gpr_avl_is_empty");
   gpr_cmdline_create_import = (gpr_cmdline_create_type) GetProcAddress(library, "gpr_cmdline_create");
   gpr_cmdline_add_int_import = (gpr_cmdline_add_int_type) GetProcAddress(library, "gpr_cmdline_add_int");
   gpr_cmdline_add_flag_import = (gpr_cmdline_add_flag_type) GetProcAddress(library, "gpr_cmdline_add_flag");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index e9845cd..072e29c 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -731,6 +731,12 @@
 typedef void *(*gpr_avl_get_type)(gpr_avl avl, void *key);
 extern gpr_avl_get_type gpr_avl_get_import;
 #define gpr_avl_get gpr_avl_get_import
+typedef int(*gpr_avl_maybe_get_type)(gpr_avl avl, void *key, void **value);
+extern gpr_avl_maybe_get_type gpr_avl_maybe_get_import;
+#define gpr_avl_maybe_get gpr_avl_maybe_get_import
+typedef int(*gpr_avl_is_empty_type)(gpr_avl avl);
+extern gpr_avl_is_empty_type gpr_avl_is_empty_import;
+#define gpr_avl_is_empty gpr_avl_is_empty_import
 typedef gpr_cmdline *(*gpr_cmdline_create_type)(const char *description);
 extern gpr_cmdline_create_type gpr_cmdline_create_import;
 #define gpr_cmdline_create gpr_cmdline_create_import
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index f753b6f..24ee338 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -62,7 +62,7 @@
   gpr_event_set(&a->done_thd, (void *)1);
 }
 
-static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   thd_args *a = arg;
   gpr_event_set(&a->done_write, (void *)1);
 }
@@ -81,7 +81,7 @@
   gpr_event read_done;
 } read_args;
 
-static void read_done(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void read_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   read_args *a = arg;
   a->validator(&a->incoming);
   gpr_event_set(&a->read_done, (void *)1);
diff --git a/test/core/bad_ssl/servers/cert.c b/test/core/bad_ssl/servers/cert.c
index bd11efd..91dd9de 100644
--- a/test/core/bad_ssl/servers/cert.c
+++ b/test/core/bad_ssl/servers/cert.c
@@ -38,7 +38,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/iomgr/load_file.h"
 
 #include "test/core/bad_ssl/server_common.h"
 #include "test/core/end2end/data/ssl_test_data.h"
@@ -52,16 +52,15 @@
   grpc_server_credentials *ssl_creds;
   grpc_server *server;
   gpr_slice cert_slice, key_slice;
-  int ok;
 
   grpc_init();
 
-  cert_slice =
-      gpr_load_file("src/core/lib/tsi/test_creds/badserver.pem", 1, &ok);
-  GPR_ASSERT(ok);
-  key_slice =
-      gpr_load_file("src/core/lib/tsi/test_creds/badserver.key", 1, &ok);
-  GPR_ASSERT(ok);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "load_file", grpc_load_file("src/core/lib/tsi/test_creds/badserver.pem",
+                                  1, &cert_slice)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "load_file", grpc_load_file("src/core/lib/tsi/test_creds/badserver.key",
+                                  1, &key_slice)));
   pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice);
   pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice);
 
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 2d77bc5..f9561be 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -81,12 +81,13 @@
   return gpr_strdup("peer");
 }
 
-static void free_channel(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void free_channel(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
   grpc_channel_stack_destroy(exec_ctx, arg);
   gpr_free(arg);
 }
 
-static void free_call(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void free_call(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   grpc_call_stack_destroy(exec_ctx, arg, NULL, NULL);
   gpr_free(arg);
 }
diff --git a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
index 2322aa6..69c07d8 100644
--- a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
@@ -67,21 +67,21 @@
 static gpr_mu g_mu;
 static bool g_fail_resolution = true;
 
-static grpc_resolved_addresses *my_resolve_address(const char *name,
-                                                   const char *addr) {
+static grpc_error *my_resolve_address(const char *name, const char *addr,
+                                      grpc_resolved_addresses **addrs) {
   gpr_mu_lock(&g_mu);
   GPR_ASSERT(0 == strcmp("test", name));
   if (g_fail_resolution) {
     g_fail_resolution = false;
     gpr_mu_unlock(&g_mu);
-    return NULL;
+    return GRPC_ERROR_CREATE("Forced Failure");
   } else {
     gpr_mu_unlock(&g_mu);
-    grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
-    addrs->naddrs = 1;
-    addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
-    addrs->addrs[0].len = 123;
-    return addrs;
+    *addrs = gpr_malloc(sizeof(**addrs));
+    (*addrs)->naddrs = 1;
+    (*addrs)->addrs = gpr_malloc(sizeof(*(*addrs)->addrs));
+    (*addrs)->addrs[0].len = 123;
+    return GRPC_ERROR_NONE;
   }
 }
 
@@ -100,7 +100,7 @@
   return resolver;
 }
 
-static void on_done(grpc_exec_ctx *exec_ctx, void *ev, bool success) {
+static void on_done(grpc_exec_ctx *exec_ctx, void *ev, grpc_error *error) {
   gpr_event_set(ev, (void *)1);
 }
 
diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c
index 63371a6..1b51424 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -65,8 +65,8 @@
 static struct rpc_state state;
 static grpc_closure on_read;
 
-static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  GPR_ASSERT(success);
+static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   gpr_slice_buffer_move_into(&state.temp_incoming_buffer,
                              &state.incoming_buffer);
   gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, magic is %" PRIuPTR " bytes",
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 46e060e..65a8deb 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -273,7 +273,9 @@
 }
 
 int external_dns_works(const char *host) {
-  grpc_resolved_addresses *res = grpc_blocking_resolve_address(host, "80");
+  grpc_resolved_addresses *res;
+  grpc_error *error = grpc_blocking_resolve_address(host, "80", &res);
+  GRPC_ERROR_UNREF(error);
   if (res != NULL) {
     grpc_resolved_addresses_destroy(res);
     return 1;
diff --git a/test/core/end2end/fixtures/h2_fd.c b/test/core/end2end/fixtures/h2_fd.c
index e938fe7..89fa025 100644
--- a/test/core/end2end/fixtures/h2_fd.c
+++ b/test/core/end2end/fixtures/h2_fd.c
@@ -54,8 +54,8 @@
   GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
   flags = fcntl(sv[1], F_GETFL, 0);
   GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
-  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index dd93c4a..13b8bf7 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -187,21 +187,25 @@
 typedef struct addr_req {
   grpc_timer timer;
   char *addr;
-  grpc_resolve_cb cb;
-  void *arg;
+  grpc_closure *on_done;
+  grpc_resolved_addresses **addrs;
 } addr_req;
 
-static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg,
+                           grpc_error *error) {
   addr_req *r = arg;
 
-  if (success && 0 == strcmp(r->addr, "server")) {
+  if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) {
     grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
     addrs->naddrs = 1;
     addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
     addrs->addrs[0].len = 0;
-    r->cb(exec_ctx, r->arg, addrs);
+    *r->addrs = addrs;
+    grpc_exec_ctx_sched(exec_ctx, r->on_done, GRPC_ERROR_NONE, NULL);
   } else {
-    r->cb(exec_ctx, r->arg, NULL);
+    grpc_exec_ctx_sched(
+        exec_ctx, r->on_done,
+        GRPC_ERROR_CREATE_REFERENCING("Resolution failed", &error, 1), NULL);
   }
 
   gpr_free(r->addr);
@@ -209,12 +213,12 @@
 }
 
 void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
-                        const char *default_port, grpc_resolve_cb cb,
-                        void *arg) {
+                        const char *default_port, grpc_closure *on_done,
+                        grpc_resolved_addresses **addresses) {
   addr_req *r = gpr_malloc(sizeof(*r));
   r->addr = gpr_strdup(addr);
-  r->cb = cb;
-  r->arg = arg;
+  r->on_done = on_done;
+  r->addrs = addresses;
   grpc_timer_init(exec_ctx, &r->timer,
                   gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                                gpr_time_from_seconds(1, GPR_TIMESPAN)),
@@ -240,11 +244,11 @@
   gpr_timespec deadline;
 } future_connect;
 
-static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   future_connect *fc = arg;
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     *fc->ep = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, fc->closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, fc->closure, GRPC_ERROR_REF(error), NULL);
   } else if (g_server != NULL) {
     grpc_endpoint *client;
     grpc_endpoint *server;
@@ -256,7 +260,7 @@
     grpc_server_setup_transport(exec_ctx, g_server, transport, NULL, NULL);
     grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
 
-    grpc_exec_ctx_enqueue(exec_ctx, fc->closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, fc->closure, GRPC_ERROR_NONE, NULL);
   } else {
     sched_connect(exec_ctx, fc->closure, fc->ep, fc->deadline);
   }
@@ -267,7 +271,8 @@
                           grpc_endpoint **ep, gpr_timespec deadline) {
   if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) {
     *ep = NULL;
-    grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, closure,
+                        GRPC_ERROR_CREATE("Connect deadline exceeded"), NULL);
     return;
   }
 
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0170e921ff5d052b228a26529116ea47fe9d3f0b b/test/core/end2end/fuzzers/api_fuzzer_corpus/0170e921ff5d052b228a26529116ea47fe9d3f0b
new file mode 100644
index 0000000..e837f03
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0170e921ff5d052b228a26529116ea47fe9d3f0b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/01a344a0256386cc8abb8dcb65cb55e1244f7f97 b/test/core/end2end/fuzzers/api_fuzzer_corpus/01a344a0256386cc8abb8dcb65cb55e1244f7f97
new file mode 100644
index 0000000..5ec993f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/01a344a0256386cc8abb8dcb65cb55e1244f7f97
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/01c59f0a030fa11c4af1b7c0cc85846e9ef3f6b9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/01c59f0a030fa11c4af1b7c0cc85846e9ef3f6b9
new file mode 100644
index 0000000..a836e05
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/01c59f0a030fa11c4af1b7c0cc85846e9ef3f6b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06b63ac01c261518e291461fb4707cb29d74e9c5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/06b63ac01c261518e291461fb4707cb29d74e9c5
new file mode 100644
index 0000000..8d2f820
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06b63ac01c261518e291461fb4707cb29d74e9c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06eced19ea6819d7b0855c62da49a193b50067ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/06eced19ea6819d7b0855c62da49a193b50067ab
new file mode 100644
index 0000000..ea4fa72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06eced19ea6819d7b0855c62da49a193b50067ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06eee533524c6723881c1591956edf704e0180d9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/06eee533524c6723881c1591956edf704e0180d9
new file mode 100644
index 0000000..4335fc7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06eee533524c6723881c1591956edf704e0180d9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0783c943aa7cdb8fdef5f7b1cf73e2bb2daf17f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0783c943aa7cdb8fdef5f7b1cf73e2bb2daf17f4
new file mode 100644
index 0000000..f8b4c6e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0783c943aa7cdb8fdef5f7b1cf73e2bb2daf17f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0963f5f7578c64e9c17d0ad9e4a99ced875cf813 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0963f5f7578c64e9c17d0ad9e4a99ced875cf813
new file mode 100644
index 0000000..bcff006
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0963f5f7578c64e9c17d0ad9e4a99ced875cf813
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a90826e3173642be15ea005c2cbe8ca36ac1c3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a90826e3173642be15ea005c2cbe8ca36ac1c3d
new file mode 100644
index 0000000..bb6cf96
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a90826e3173642be15ea005c2cbe8ca36ac1c3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0b151bf8080f87bd38c9b8521b3b96c40c708463 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b151bf8080f87bd38c9b8521b3b96c40c708463
new file mode 100644
index 0000000..8459a66
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0b151bf8080f87bd38c9b8521b3b96c40c708463
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0bf51cb435845a49311a7ddc7341b5cfc8e5ab10 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0bf51cb435845a49311a7ddc7341b5cfc8e5ab10
new file mode 100644
index 0000000..b919511
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0bf51cb435845a49311a7ddc7341b5cfc8e5ab10
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0deeaca17aa93f66291407d3d2438685be5b85ba b/test/core/end2end/fuzzers/api_fuzzer_corpus/0deeaca17aa93f66291407d3d2438685be5b85ba
new file mode 100644
index 0000000..14680a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0deeaca17aa93f66291407d3d2438685be5b85ba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfd0ea582476b3861106c143c70d7af0f3d1357 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfd0ea582476b3861106c143c70d7af0f3d1357
new file mode 100644
index 0000000..3695055
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfd0ea582476b3861106c143c70d7af0f3d1357
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0e91ce40cf8882adc75b8b532556d48a2b605ced b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e91ce40cf8882adc75b8b532556d48a2b605ced
new file mode 100644
index 0000000..9d0b415
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e91ce40cf8882adc75b8b532556d48a2b605ced
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/10f53c34f02d8c051fe0b8759aec08057433a497 b/test/core/end2end/fuzzers/api_fuzzer_corpus/10f53c34f02d8c051fe0b8759aec08057433a497
new file mode 100644
index 0000000..471890c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/10f53c34f02d8c051fe0b8759aec08057433a497
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/110e019793b395202dfd8b499edc372cdaccff21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/110e019793b395202dfd8b499edc372cdaccff21
new file mode 100644
index 0000000..3a148cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/110e019793b395202dfd8b499edc372cdaccff21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1239eef13562df4ff59856900eee2f871a2fd0f3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1239eef13562df4ff59856900eee2f871a2fd0f3
new file mode 100644
index 0000000..ce1c1bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1239eef13562df4ff59856900eee2f871a2fd0f3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/15890f893ee7bddcc08f831d684b10d19c369def b/test/core/end2end/fuzzers/api_fuzzer_corpus/15890f893ee7bddcc08f831d684b10d19c369def
new file mode 100644
index 0000000..6d80a11
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/15890f893ee7bddcc08f831d684b10d19c369def
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1727c0f6369bfb17d1b40ffa3d3f6b8be8a45c62 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1727c0f6369bfb17d1b40ffa3d3f6b8be8a45c62
new file mode 100644
index 0000000..8c8a103
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1727c0f6369bfb17d1b40ffa3d3f6b8be8a45c62
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/179817dab786637b3621ace60a9ab4c7c79432a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/179817dab786637b3621ace60a9ab4c7c79432a4
new file mode 100644
index 0000000..cf3531f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/179817dab786637b3621ace60a9ab4c7c79432a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17fa8e029e35c88857b7abcad88609cf2d1ca9a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17fa8e029e35c88857b7abcad88609cf2d1ca9a4
new file mode 100644
index 0000000..83c2b4f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17fa8e029e35c88857b7abcad88609cf2d1ca9a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1870298c7042983e7716097018a031d105e397fd b/test/core/end2end/fuzzers/api_fuzzer_corpus/1870298c7042983e7716097018a031d105e397fd
new file mode 100644
index 0000000..42a78f4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1870298c7042983e7716097018a031d105e397fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1917c5996ac82e13143a414eb9448f171fdd751a b/test/core/end2end/fuzzers/api_fuzzer_corpus/1917c5996ac82e13143a414eb9448f171fdd751a
new file mode 100644
index 0000000..dc4176b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1917c5996ac82e13143a414eb9448f171fdd751a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/19549ded404f9a9581d32a1827da96ff1420f0ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/19549ded404f9a9581d32a1827da96ff1420f0ae
new file mode 100644
index 0000000..116ac96
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/19549ded404f9a9581d32a1827da96ff1420f0ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b09a1e5994952cda58b8339492f6850936a61f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b09a1e5994952cda58b8339492f6850936a61f4
new file mode 100644
index 0000000..86af616
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b09a1e5994952cda58b8339492f6850936a61f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1cd257e53b8d5a57c9feabcfd9f8f22c30cdb4a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cd257e53b8d5a57c9feabcfd9f8f22c30cdb4a8
new file mode 100644
index 0000000..3c4a548
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cd257e53b8d5a57c9feabcfd9f8f22c30cdb4a8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1fd33a83549fb9fc5e7d05a2c308a044b7c9b167 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1fd33a83549fb9fc5e7d05a2c308a044b7c9b167
new file mode 100644
index 0000000..8385f54
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1fd33a83549fb9fc5e7d05a2c308a044b7c9b167
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/202a15693f991889b5fdd97f016a5410778b07e1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/202a15693f991889b5fdd97f016a5410778b07e1
new file mode 100644
index 0000000..70df23d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/202a15693f991889b5fdd97f016a5410778b07e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/20a10c9a0c8cc48fd6317000f70070a0b2451e60 b/test/core/end2end/fuzzers/api_fuzzer_corpus/20a10c9a0c8cc48fd6317000f70070a0b2451e60
new file mode 100644
index 0000000..9baa758
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/20a10c9a0c8cc48fd6317000f70070a0b2451e60
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/21357c3613a47180eb668b1c6c849ce9096a46eb b/test/core/end2end/fuzzers/api_fuzzer_corpus/21357c3613a47180eb668b1c6c849ce9096a46eb
new file mode 100644
index 0000000..4ed1578
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/21357c3613a47180eb668b1c6c849ce9096a46eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2372fe3d96fda1dae8846a781905c6c408555d3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/2372fe3d96fda1dae8846a781905c6c408555d3a
new file mode 100644
index 0000000..d29897c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2372fe3d96fda1dae8846a781905c6c408555d3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/23982956d17d2f55e61a5d9111b1c0c7ee530214 b/test/core/end2end/fuzzers/api_fuzzer_corpus/23982956d17d2f55e61a5d9111b1c0c7ee530214
new file mode 100644
index 0000000..146b1b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/23982956d17d2f55e61a5d9111b1c0c7ee530214
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/25a2c5d4f55a083d2535b46a82e295fb169ffb32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/25a2c5d4f55a083d2535b46a82e295fb169ffb32
new file mode 100644
index 0000000..e3e284b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/25a2c5d4f55a083d2535b46a82e295fb169ffb32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2721f5503254227af744243957ee859fa903e066 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2721f5503254227af744243957ee859fa903e066
new file mode 100644
index 0000000..a14f605
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2721f5503254227af744243957ee859fa903e066
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/282003073c8b88d7ad43ce75677777cdb754228c b/test/core/end2end/fuzzers/api_fuzzer_corpus/282003073c8b88d7ad43ce75677777cdb754228c
new file mode 100644
index 0000000..154f3bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/282003073c8b88d7ad43ce75677777cdb754228c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2858613c057a236dbe306cca44df29232f6b48b3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2858613c057a236dbe306cca44df29232f6b48b3
new file mode 100644
index 0000000..8f93474
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2858613c057a236dbe306cca44df29232f6b48b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/295d24a7705fe1821606f9224f241a7596481bed b/test/core/end2end/fuzzers/api_fuzzer_corpus/295d24a7705fe1821606f9224f241a7596481bed
new file mode 100644
index 0000000..58a4814
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/295d24a7705fe1821606f9224f241a7596481bed
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a08eb351e08f0e6ac1e1416b43ff962a4e3735c b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a08eb351e08f0e6ac1e1416b43ff962a4e3735c
new file mode 100644
index 0000000..c1a88b0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a08eb351e08f0e6ac1e1416b43ff962a4e3735c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a1d70b04f4aba0ec93899485f0807a209a4b207 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a1d70b04f4aba0ec93899485f0807a209a4b207
new file mode 100644
index 0000000..a04bc00
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a1d70b04f4aba0ec93899485f0807a209a4b207
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a2ca2f6a1c03067f87bad61515688edc234bacc b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a2ca2f6a1c03067f87bad61515688edc234bacc
new file mode 100644
index 0000000..48d26da
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a2ca2f6a1c03067f87bad61515688edc234bacc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2aaee068ca624dcb746af9dc14591b24db033ffc b/test/core/end2end/fuzzers/api_fuzzer_corpus/2aaee068ca624dcb746af9dc14591b24db033ffc
new file mode 100644
index 0000000..ee202ea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2aaee068ca624dcb746af9dc14591b24db033ffc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce30739d22f5380f96400f261fd26e95cc33927 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce30739d22f5380f96400f261fd26e95cc33927
new file mode 100644
index 0000000..725aa45
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce30739d22f5380f96400f261fd26e95cc33927
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2e40d861a9fec3742c31971b583e28bf40e28dbe b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e40d861a9fec3742c31971b583e28bf40e28dbe
new file mode 100644
index 0000000..8159fcb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2e40d861a9fec3742c31971b583e28bf40e28dbe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ec78409a7d3625126387512a1c58cae2ff0bcf7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ec78409a7d3625126387512a1c58cae2ff0bcf7
new file mode 100644
index 0000000..387120d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ec78409a7d3625126387512a1c58cae2ff0bcf7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ffb878075ebb3d2d778c8aabcb0e96cb51060f0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ffb878075ebb3d2d778c8aabcb0e96cb51060f0
new file mode 100644
index 0000000..cb10119
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ffb878075ebb3d2d778c8aabcb0e96cb51060f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30c74b7b5c92bb602d26c3d703c267e288b432a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/30c74b7b5c92bb602d26c3d703c267e288b432a2
new file mode 100644
index 0000000..c2552d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30c74b7b5c92bb602d26c3d703c267e288b432a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/31498be283beb45294fb96f15b3af4e7de0ce584 b/test/core/end2end/fuzzers/api_fuzzer_corpus/31498be283beb45294fb96f15b3af4e7de0ce584
new file mode 100644
index 0000000..dfad08c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/31498be283beb45294fb96f15b3af4e7de0ce584
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/314ea0a2c481639b6559b063399299259c43c9bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/314ea0a2c481639b6559b063399299259c43c9bb
new file mode 100644
index 0000000..6a06838
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/314ea0a2c481639b6559b063399299259c43c9bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/31ef9c4ed85ae1b4e8a027fc5a1d3037dbbf3b3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/31ef9c4ed85ae1b4e8a027fc5a1d3037dbbf3b3a
new file mode 100644
index 0000000..2edcd8e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/31ef9c4ed85ae1b4e8a027fc5a1d3037dbbf3b3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/327e5a755e3307b121700f1ba23000a844e70596 b/test/core/end2end/fuzzers/api_fuzzer_corpus/327e5a755e3307b121700f1ba23000a844e70596
new file mode 100644
index 0000000..b2152cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/327e5a755e3307b121700f1ba23000a844e70596
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3396a31b1075465bf358eb7836e6f5347a0be591 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3396a31b1075465bf358eb7836e6f5347a0be591
new file mode 100644
index 0000000..8dd0ffc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3396a31b1075465bf358eb7836e6f5347a0be591
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/350a1f6d0fe784667d7ae78e1ed783cdf2263bfd b/test/core/end2end/fuzzers/api_fuzzer_corpus/350a1f6d0fe784667d7ae78e1ed783cdf2263bfd
new file mode 100644
index 0000000..83f2053
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/350a1f6d0fe784667d7ae78e1ed783cdf2263bfd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/35cf9a1a6f81db0829d854fd3716916bae081c8c b/test/core/end2end/fuzzers/api_fuzzer_corpus/35cf9a1a6f81db0829d854fd3716916bae081c8c
new file mode 100644
index 0000000..836e04a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/35cf9a1a6f81db0829d854fd3716916bae081c8c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/368f9368e43f7e743653d46360836b3db1b1ba8a b/test/core/end2end/fuzzers/api_fuzzer_corpus/368f9368e43f7e743653d46360836b3db1b1ba8a
new file mode 100644
index 0000000..dae7009
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/368f9368e43f7e743653d46360836b3db1b1ba8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/36dea0ab5bc764c2eb2f428bcbe2786e64da8bd3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/36dea0ab5bc764c2eb2f428bcbe2786e64da8bd3
new file mode 100644
index 0000000..5f8de54
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/36dea0ab5bc764c2eb2f428bcbe2786e64da8bd3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/376f42635e918cc28706b82ad8923cc7401aa9e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/376f42635e918cc28706b82ad8923cc7401aa9e6
new file mode 100644
index 0000000..32500f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/376f42635e918cc28706b82ad8923cc7401aa9e6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/37cf256347732e86fa92089847b7381e964cc83f b/test/core/end2end/fuzzers/api_fuzzer_corpus/37cf256347732e86fa92089847b7381e964cc83f
new file mode 100644
index 0000000..a737c85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/37cf256347732e86fa92089847b7381e964cc83f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/38eb06643f87fff21483433dc4169e0388b0c9e1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/38eb06643f87fff21483433dc4169e0388b0c9e1
new file mode 100644
index 0000000..ff983d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/38eb06643f87fff21483433dc4169e0388b0c9e1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3b114f7e66bf6cbf256a5e656ab6620e3f31277f b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b114f7e66bf6cbf256a5e656ab6620e3f31277f
new file mode 100644
index 0000000..1be8399
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3b114f7e66bf6cbf256a5e656ab6620e3f31277f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3db644687c6a09fae4267f05b63a969f28024f87 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3db644687c6a09fae4267f05b63a969f28024f87
new file mode 100644
index 0000000..1a32811
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3db644687c6a09fae4267f05b63a969f28024f87
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3dc1bcb27ed0616a2b905025a8898759d94a934d b/test/core/end2end/fuzzers/api_fuzzer_corpus/3dc1bcb27ed0616a2b905025a8898759d94a934d
new file mode 100644
index 0000000..a4a8de4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3dc1bcb27ed0616a2b905025a8898759d94a934d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2e5f90e1a93df61a1c9c09b8c9116149eec526 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2e5f90e1a93df61a1c9c09b8c9116149eec526
new file mode 100644
index 0000000..d1451d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2e5f90e1a93df61a1c9c09b8c9116149eec526
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3f31d328c16207904d201406f7e9708360d5799b b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f31d328c16207904d201406f7e9708360d5799b
new file mode 100644
index 0000000..4791cfd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f31d328c16207904d201406f7e9708360d5799b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4141d93d6c387967967844423a6a83ad1793010a b/test/core/end2end/fuzzers/api_fuzzer_corpus/4141d93d6c387967967844423a6a83ad1793010a
new file mode 100644
index 0000000..9fd0385
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4141d93d6c387967967844423a6a83ad1793010a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a4675803915c9dafe85b8026c93a0ca9c498233 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a4675803915c9dafe85b8026c93a0ca9c498233
new file mode 100644
index 0000000..e72cdf2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a4675803915c9dafe85b8026c93a0ca9c498233
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d345f45f808c5b0541976b5dff98c603611e9ab b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d345f45f808c5b0541976b5dff98c603611e9ab
new file mode 100644
index 0000000..47c4276
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d345f45f808c5b0541976b5dff98c603611e9ab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4d5e7091c1c67867f2760543d9a8a7256007bdef b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d5e7091c1c67867f2760543d9a8a7256007bdef
new file mode 100644
index 0000000..418b06b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4d5e7091c1c67867f2760543d9a8a7256007bdef
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4e8dbf3eb7d11a4fdb994f281454be2a7ebb091c b/test/core/end2end/fuzzers/api_fuzzer_corpus/4e8dbf3eb7d11a4fdb994f281454be2a7ebb091c
new file mode 100644
index 0000000..c2895f6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4e8dbf3eb7d11a4fdb994f281454be2a7ebb091c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4eedb47e422ce761fc5b279582e56c7d1f3ed180 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4eedb47e422ce761fc5b279582e56c7d1f3ed180
new file mode 100644
index 0000000..e75ebcf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4eedb47e422ce761fc5b279582e56c7d1f3ed180
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5109721ea8f74b08d455968fce90dd74c29aa95a b/test/core/end2end/fuzzers/api_fuzzer_corpus/5109721ea8f74b08d455968fce90dd74c29aa95a
new file mode 100644
index 0000000..b0fc4c1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5109721ea8f74b08d455968fce90dd74c29aa95a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51be7e2267e32f2eb8079349882f8247dc397d0f b/test/core/end2end/fuzzers/api_fuzzer_corpus/51be7e2267e32f2eb8079349882f8247dc397d0f
new file mode 100644
index 0000000..3071957
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51be7e2267e32f2eb8079349882f8247dc397d0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/521e1e27b0997a0dc168f628e8a0497f7f93ea6d b/test/core/end2end/fuzzers/api_fuzzer_corpus/521e1e27b0997a0dc168f628e8a0497f7f93ea6d
new file mode 100644
index 0000000..60a88d4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/521e1e27b0997a0dc168f628e8a0497f7f93ea6d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/541e87b9d3dc75ad40cb47935ed4de83b25af5b9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/541e87b9d3dc75ad40cb47935ed4de83b25af5b9
new file mode 100644
index 0000000..4eabbd5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/541e87b9d3dc75ad40cb47935ed4de83b25af5b9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5611060a04db105e03cc74da57352b8a09c411e0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5611060a04db105e03cc74da57352b8a09c411e0
new file mode 100644
index 0000000..cd30ed8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5611060a04db105e03cc74da57352b8a09c411e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/56e0bd235d4ea1de80d753b2b12d03d43cd0aa06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/56e0bd235d4ea1de80d753b2b12d03d43cd0aa06
new file mode 100644
index 0000000..9bd9fe4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/56e0bd235d4ea1de80d753b2b12d03d43cd0aa06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57d4ef9e72f97aa8a1e6689f3be092fc2b24315c b/test/core/end2end/fuzzers/api_fuzzer_corpus/57d4ef9e72f97aa8a1e6689f3be092fc2b24315c
new file mode 100644
index 0000000..59226aa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57d4ef9e72f97aa8a1e6689f3be092fc2b24315c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5967be7b53e3bac677c726d30a513949e06e1fde b/test/core/end2end/fuzzers/api_fuzzer_corpus/5967be7b53e3bac677c726d30a513949e06e1fde
new file mode 100644
index 0000000..76c0024
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5967be7b53e3bac677c726d30a513949e06e1fde
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/598c513564bc043f831876ea61cb8283d43f6726 b/test/core/end2end/fuzzers/api_fuzzer_corpus/598c513564bc043f831876ea61cb8283d43f6726
new file mode 100644
index 0000000..9c9acf2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/598c513564bc043f831876ea61cb8283d43f6726
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/59db3f98b38747d4a35524c1b3d31b5e90f53775 b/test/core/end2end/fuzzers/api_fuzzer_corpus/59db3f98b38747d4a35524c1b3d31b5e90f53775
new file mode 100644
index 0000000..46274c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/59db3f98b38747d4a35524c1b3d31b5e90f53775
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5c37a2f980223e737574dba8239378f643800c28 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c37a2f980223e737574dba8239378f643800c28
new file mode 100644
index 0000000..3e3432f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c37a2f980223e737574dba8239378f643800c28
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddce6103cb33bc58571c8135b620443740e3646 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddce6103cb33bc58571c8135b620443740e3646
new file mode 100644
index 0000000..05798a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ddce6103cb33bc58571c8135b620443740e3646
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5e31ededf3b3189d252148c450de7a8778653e72 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e31ededf3b3189d252148c450de7a8778653e72
new file mode 100644
index 0000000..f8d4762
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e31ededf3b3189d252148c450de7a8778653e72
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f61659c332f6153f9a59746bc02064155443b4a b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f61659c332f6153f9a59746bc02064155443b4a
new file mode 100644
index 0000000..790bcc1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f61659c332f6153f9a59746bc02064155443b4a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/60ad6847b1fe72ee81decf28dcffa30ce372af6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/60ad6847b1fe72ee81decf28dcffa30ce372af6a
new file mode 100644
index 0000000..c113b0b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/60ad6847b1fe72ee81decf28dcffa30ce372af6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0
new file mode 100644
index 0000000..ea9e457
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6619768ddd830ebe29021e827961fddb78751086 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6619768ddd830ebe29021e827961fddb78751086
new file mode 100644
index 0000000..2508dc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6619768ddd830ebe29021e827961fddb78751086
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/682fdabcfc7243e9c93108d6b2d7d3e920e81970 b/test/core/end2end/fuzzers/api_fuzzer_corpus/682fdabcfc7243e9c93108d6b2d7d3e920e81970
new file mode 100644
index 0000000..0138558
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/682fdabcfc7243e9c93108d6b2d7d3e920e81970
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad7afcf2d12025faf0e1812ee7a0a5d754620c6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad7afcf2d12025faf0e1812ee7a0a5d754620c6
new file mode 100644
index 0000000..c45f7e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad7afcf2d12025faf0e1812ee7a0a5d754620c6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae8b3afc4f6e3a26fec5eaeb2bf64727927552b b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae8b3afc4f6e3a26fec5eaeb2bf64727927552b
new file mode 100644
index 0000000..0418038
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae8b3afc4f6e3a26fec5eaeb2bf64727927552b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6be9f2d2967566ac929c27a27de40af792a6da90 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6be9f2d2967566ac929c27a27de40af792a6da90
new file mode 100644
index 0000000..fb7267a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6be9f2d2967566ac929c27a27de40af792a6da90
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6c34a6b47ef9e11e02f7675087d888c2c994b010 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c34a6b47ef9e11e02f7675087d888c2c994b010
new file mode 100644
index 0000000..243e93f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6c34a6b47ef9e11e02f7675087d888c2c994b010
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce0f95767e8b1c58ff313d10f1a3eb1f9ab8496 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce0f95767e8b1c58ff313d10f1a3eb1f9ab8496
new file mode 100644
index 0000000..f1dcb2c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ce0f95767e8b1c58ff313d10f1a3eb1f9ab8496
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6cfe000a50ad8b908b3efa3af94c5df6382ff33d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6cfe000a50ad8b908b3efa3af94c5df6382ff33d
new file mode 100644
index 0000000..5661854
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6cfe000a50ad8b908b3efa3af94c5df6382ff33d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6d6d70df4499b8595851100ffb833d397cc87a18 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6d6d70df4499b8595851100ffb833d397cc87a18
new file mode 100644
index 0000000..1a770cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6d6d70df4499b8595851100ffb833d397cc87a18
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6e3d43e98d7be45ecc1863eedfeb85a4cae4a007 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e3d43e98d7be45ecc1863eedfeb85a4cae4a007
new file mode 100644
index 0000000..38e2e33
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e3d43e98d7be45ecc1863eedfeb85a4cae4a007
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6e77e1cd328bb98d954043230716863c5133c1c4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e77e1cd328bb98d954043230716863c5133c1c4
new file mode 100644
index 0000000..f321eab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6e77e1cd328bb98d954043230716863c5133c1c4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6f68ff31046fd15930657516873b8835fdbadfe3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f68ff31046fd15930657516873b8835fdbadfe3
new file mode 100644
index 0000000..be37cac
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6f68ff31046fd15930657516873b8835fdbadfe3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71f9eafe17e974062938a6a12433ce723fe07d40 b/test/core/end2end/fuzzers/api_fuzzer_corpus/71f9eafe17e974062938a6a12433ce723fe07d40
new file mode 100644
index 0000000..51cc9f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71f9eafe17e974062938a6a12433ce723fe07d40
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72160b48e0995ee82f116d77a7fb23a028c10932 b/test/core/end2end/fuzzers/api_fuzzer_corpus/72160b48e0995ee82f116d77a7fb23a028c10932
new file mode 100644
index 0000000..be6505a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72160b48e0995ee82f116d77a7fb23a028c10932
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/756d77e9fb9ed9dac1db0b1c8cdcc6e05e47329b b/test/core/end2end/fuzzers/api_fuzzer_corpus/756d77e9fb9ed9dac1db0b1c8cdcc6e05e47329b
new file mode 100644
index 0000000..e662e29
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/756d77e9fb9ed9dac1db0b1c8cdcc6e05e47329b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7590589db6b56b4e7db9333fba8d723b6461e0a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7590589db6b56b4e7db9333fba8d723b6461e0a6
new file mode 100644
index 0000000..93a98b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7590589db6b56b4e7db9333fba8d723b6461e0a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/75a242a8e6a0c453ac785fe6495d408e9650e17d b/test/core/end2end/fuzzers/api_fuzzer_corpus/75a242a8e6a0c453ac785fe6495d408e9650e17d
new file mode 100644
index 0000000..0198181
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/75a242a8e6a0c453ac785fe6495d408e9650e17d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/78d8b2a1732c4528d6acdb21c236f417a0f85798 b/test/core/end2end/fuzzers/api_fuzzer_corpus/78d8b2a1732c4528d6acdb21c236f417a0f85798
new file mode 100644
index 0000000..77c2b28
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/78d8b2a1732c4528d6acdb21c236f417a0f85798
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/79975e5fb34f3569b0d2e40d34d6f7ab1bf82cf2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/79975e5fb34f3569b0d2e40d34d6f7ab1bf82cf2
new file mode 100644
index 0000000..ad1b3b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/79975e5fb34f3569b0d2e40d34d6f7ab1bf82cf2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7b44a92a28ff5c96be7c4dae5c56a9e5fa272ad3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b44a92a28ff5c96be7c4dae5c56a9e5fa272ad3
new file mode 100644
index 0000000..dac2af4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b44a92a28ff5c96be7c4dae5c56a9e5fa272ad3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7cfe9fd65c3daa43067dfc99dac2814b763b9f48 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cfe9fd65c3daa43067dfc99dac2814b763b9f48
new file mode 100644
index 0000000..372e293
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cfe9fd65c3daa43067dfc99dac2814b763b9f48
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7d3ff63f0b0019fef80e5e3cd82de8dfbcd07103 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d3ff63f0b0019fef80e5e3cd82de8dfbcd07103
new file mode 100644
index 0000000..0f58ec7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7d3ff63f0b0019fef80e5e3cd82de8dfbcd07103
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7f2a2a365669c88559036ed998b074b1b9a31e0b b/test/core/end2end/fuzzers/api_fuzzer_corpus/7f2a2a365669c88559036ed998b074b1b9a31e0b
new file mode 100644
index 0000000..be6cc53
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7f2a2a365669c88559036ed998b074b1b9a31e0b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/81437c61aeca9becc91003af7b835dc65a3e03e4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/81437c61aeca9becc91003af7b835dc65a3e03e4
new file mode 100644
index 0000000..72700d7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/81437c61aeca9becc91003af7b835dc65a3e03e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8272e45483cb4cc7113b0ffad71f9218542f9cd7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8272e45483cb4cc7113b0ffad71f9218542f9cd7
new file mode 100644
index 0000000..0da408e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8272e45483cb4cc7113b0ffad71f9218542f9cd7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/83e2bd562704e16ac57589b4273d0c61775d7c9c b/test/core/end2end/fuzzers/api_fuzzer_corpus/83e2bd562704e16ac57589b4273d0c61775d7c9c
new file mode 100644
index 0000000..40de3dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/83e2bd562704e16ac57589b4273d0c61775d7c9c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/84505278558cc406dc36109deab239f1e4cf1518 b/test/core/end2end/fuzzers/api_fuzzer_corpus/84505278558cc406dc36109deab239f1e4cf1518
new file mode 100644
index 0000000..d681d33
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/84505278558cc406dc36109deab239f1e4cf1518
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8525fa2b11288eda66418be4ecfcf8d7731d75a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8525fa2b11288eda66418be4ecfcf8d7731d75a6
new file mode 100644
index 0000000..b723cc1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8525fa2b11288eda66418be4ecfcf8d7731d75a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/85a50177266a832eca0563d37ccb03890f12c665 b/test/core/end2end/fuzzers/api_fuzzer_corpus/85a50177266a832eca0563d37ccb03890f12c665
new file mode 100644
index 0000000..7c2870f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/85a50177266a832eca0563d37ccb03890f12c665
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/85afba0cb1eb440ed95ee5793a70c7e5d8465148 b/test/core/end2end/fuzzers/api_fuzzer_corpus/85afba0cb1eb440ed95ee5793a70c7e5d8465148
new file mode 100644
index 0000000..1fc35b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/85afba0cb1eb440ed95ee5793a70c7e5d8465148
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/871196ccb877b7c6c7d6cafe3324fde440706de3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/871196ccb877b7c6c7d6cafe3324fde440706de3
new file mode 100644
index 0000000..81d2d75
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/871196ccb877b7c6c7d6cafe3324fde440706de3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a13b47235d2967f5a5419cb0ad8d241a750a365 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a13b47235d2967f5a5419cb0ad8d241a750a365
new file mode 100644
index 0000000..ca96913
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a13b47235d2967f5a5419cb0ad8d241a750a365
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a6ccd18dbc530ed34afd4a73beeff0449040c25 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a6ccd18dbc530ed34afd4a73beeff0449040c25
new file mode 100644
index 0000000..93fc40f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a6ccd18dbc530ed34afd4a73beeff0449040c25
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8bdd4dc6dee56fb6965655425ca378f784a42b6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/8bdd4dc6dee56fb6965655425ca378f784a42b6a
new file mode 100644
index 0000000..b54fd86
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8bdd4dc6dee56fb6965655425ca378f784a42b6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c6776521d0f100708ecb9f8504e572d586b8a21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c6776521d0f100708ecb9f8504e572d586b8a21
new file mode 100644
index 0000000..be00bec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c6776521d0f100708ecb9f8504e572d586b8a21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8de197bbdf4deaea5bd21af25c0b5c5f03b231ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/8de197bbdf4deaea5bd21af25c0b5c5f03b231ae
new file mode 100644
index 0000000..5a98f90
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8de197bbdf4deaea5bd21af25c0b5c5f03b231ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8e226a7f67b7c6e9d439c3627bfa5644af992593 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e226a7f67b7c6e9d439c3627bfa5644af992593
new file mode 100644
index 0000000..a08862a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e226a7f67b7c6e9d439c3627bfa5644af992593
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722 b/test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722
new file mode 100644
index 0000000..f0dbace
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92882ccad7fc3e7bc1df7dfa5954a6d591d5dbc2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92882ccad7fc3e7bc1df7dfa5954a6d591d5dbc2
new file mode 100644
index 0000000..b53afb9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92882ccad7fc3e7bc1df7dfa5954a6d591d5dbc2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92a87c7a2f2e336f92529bc40deee614dd8b4486 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92a87c7a2f2e336f92529bc40deee614dd8b4486
new file mode 100644
index 0000000..4d31488
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92a87c7a2f2e336f92529bc40deee614dd8b4486
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92e8c16eb9a816c5944ecb76cf9af08f05930aeb b/test/core/end2end/fuzzers/api_fuzzer_corpus/92e8c16eb9a816c5944ecb76cf9af08f05930aeb
new file mode 100644
index 0000000..ddc69e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92e8c16eb9a816c5944ecb76cf9af08f05930aeb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9345e2de4f0476428d941c53013535fbda8a2bca b/test/core/end2end/fuzzers/api_fuzzer_corpus/9345e2de4f0476428d941c53013535fbda8a2bca
new file mode 100644
index 0000000..634bfbc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9345e2de4f0476428d941c53013535fbda8a2bca
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97539b673cb482cfa4d876df515270611b28f22a b/test/core/end2end/fuzzers/api_fuzzer_corpus/97539b673cb482cfa4d876df515270611b28f22a
new file mode 100644
index 0000000..7d23be7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97539b673cb482cfa4d876df515270611b28f22a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9b014aa18fb8c033458b6d5fdb351e60d16e8bce b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b014aa18fb8c033458b6d5fdb351e60d16e8bce
new file mode 100644
index 0000000..8c676b2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b014aa18fb8c033458b6d5fdb351e60d16e8bce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9bbb726cd811fce33aecdbcce3d287c252ed71d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bbb726cd811fce33aecdbcce3d287c252ed71d5
new file mode 100644
index 0000000..e6bd6e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9bbb726cd811fce33aecdbcce3d287c252ed71d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd5d09e1538e12b091c35d252ee43684d0f07bd b/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd5d09e1538e12b091c35d252ee43684d0f07bd
new file mode 100644
index 0000000..79ca267
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9dd5d09e1538e12b091c35d252ee43684d0f07bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9fd5c58979d17905e46ee7b76f542f7acb54d60f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9fd5c58979d17905e46ee7b76f542f7acb54d60f
new file mode 100644
index 0000000..b612d8b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9fd5c58979d17905e46ee7b76f542f7acb54d60f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a001745aa3499a11bf1cee1af077bdc85a03ef95 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a001745aa3499a11bf1cee1af077bdc85a03ef95
new file mode 100644
index 0000000..97fb1db
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a001745aa3499a11bf1cee1af077bdc85a03ef95
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a151b36f390273fb440d2e35ab93acc5540bfed6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a151b36f390273fb440d2e35ab93acc5540bfed6
new file mode 100644
index 0000000..502c838
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a151b36f390273fb440d2e35ab93acc5540bfed6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a19cc971908189b5febf6fb5e8578c91dd666715 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a19cc971908189b5febf6fb5e8578c91dd666715
new file mode 100644
index 0000000..8e331bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a19cc971908189b5febf6fb5e8578c91dd666715
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b0fdbc2160dfe8c1eed409eb60042c819a843a b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b0fdbc2160dfe8c1eed409eb60042c819a843a
new file mode 100644
index 0000000..028ca0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1b0fdbc2160dfe8c1eed409eb60042c819a843a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a34472604c8107353872e77a84873ff8a9170 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a34472604c8107353872e77a84873ff8a9170
new file mode 100644
index 0000000..5a660eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a36a34472604c8107353872e77a84873ff8a9170
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a3fcf35a54c8c88b5cc1ef76e43124bb25b61ba3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3fcf35a54c8c88b5cc1ef76e43124bb25b61ba3
new file mode 100644
index 0000000..722b611
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a3fcf35a54c8c88b5cc1ef76e43124bb25b61ba3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a44288607b76ce6df9fe7e196138a587cf4badc9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a44288607b76ce6df9fe7e196138a587cf4badc9
new file mode 100644
index 0000000..095e02e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a44288607b76ce6df9fe7e196138a587cf4badc9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a7ccc1f7db49512983fe4d42c16b2160357e3585 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a7ccc1f7db49512983fe4d42c16b2160357e3585
new file mode 100644
index 0000000..8185b0f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a7ccc1f7db49512983fe4d42c16b2160357e3585
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a7d45318db68aea203c6f661f571394b649cfd86 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a7d45318db68aea203c6f661f571394b649cfd86
new file mode 100644
index 0000000..1928f47
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a7d45318db68aea203c6f661f571394b649cfd86
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a8b5f205a578696697bc1ca381e73501c3a9b185 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8b5f205a578696697bc1ca381e73501c3a9b185
new file mode 100644
index 0000000..29b2bc1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8b5f205a578696697bc1ca381e73501c3a9b185
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa0c7fda7faff932bf36e10d15ab2180ab1bca27 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa0c7fda7faff932bf36e10d15ab2180ab1bca27
new file mode 100644
index 0000000..dad34fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa0c7fda7faff932bf36e10d15ab2180ab1bca27
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/acd5d85336bff9b38196c682864dd7a4965ac904 b/test/core/end2end/fuzzers/api_fuzzer_corpus/acd5d85336bff9b38196c682864dd7a4965ac904
new file mode 100644
index 0000000..87dd9ee
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/acd5d85336bff9b38196c682864dd7a4965ac904
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b06102e16c740796a9d30e07b9e564b65f7513da b/test/core/end2end/fuzzers/api_fuzzer_corpus/b06102e16c740796a9d30e07b9e564b65f7513da
new file mode 100644
index 0000000..70517fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b06102e16c740796a9d30e07b9e564b65f7513da
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b1e28018e26e6baaba5a907e5e6ff9b7a7942018 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b1e28018e26e6baaba5a907e5e6ff9b7a7942018
new file mode 100644
index 0000000..31e40bf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b1e28018e26e6baaba5a907e5e6ff9b7a7942018
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b2c5f4f8e2129a4201b2525cba8723241bbd8c79 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2c5f4f8e2129a4201b2525cba8723241bbd8c79
new file mode 100644
index 0000000..61188e2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2c5f4f8e2129a4201b2525cba8723241bbd8c79
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b8ba878466fc6c4e1939e38c38aa64026b055b b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b8ba878466fc6c4e1939e38c38aa64026b055b
new file mode 100644
index 0000000..3187f6a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b8ba878466fc6c4e1939e38c38aa64026b055b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b4f6d203097dcd1778f4a912cdc3af96ffb681de b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4f6d203097dcd1778f4a912cdc3af96ffb681de
new file mode 100644
index 0000000..5804a76
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4f6d203097dcd1778f4a912cdc3af96ffb681de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b51db02b904ceee344fe48179d0c784c59ca2934 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b51db02b904ceee344fe48179d0c784c59ca2934
new file mode 100644
index 0000000..352df6c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b51db02b904ceee344fe48179d0c784c59ca2934
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b63da75ca24aac41285dd14de6712179a3fbc0d1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b63da75ca24aac41285dd14de6712179a3fbc0d1
new file mode 100644
index 0000000..22e3abc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b63da75ca24aac41285dd14de6712179a3fbc0d1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b6ce8604e3c14c6867cd2a78cef144ddd2fbb4c1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6ce8604e3c14c6867cd2a78cef144ddd2fbb4c1
new file mode 100644
index 0000000..55fcf26
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6ce8604e3c14c6867cd2a78cef144ddd2fbb4c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b79553c903c06619d53395ee67896c1554def055 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b79553c903c06619d53395ee67896c1554def055
new file mode 100644
index 0000000..55fdc1e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b79553c903c06619d53395ee67896c1554def055
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b7c3f40ef32cd843e331fb49521c0d614dfbecc9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b7c3f40ef32cd843e331fb49521c0d614dfbecc9
new file mode 100644
index 0000000..4b010f4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b7c3f40ef32cd843e331fb49521c0d614dfbecc9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bedb9c38fd149bc494a65674a4af5e61dfb311 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bedb9c38fd149bc494a65674a4af5e61dfb311
new file mode 100644
index 0000000..a9c0073
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bedb9c38fd149bc494a65674a4af5e61dfb311
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b9eb50c5eb99cf0b419efa2cb8d7fdf2e71f6634 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9eb50c5eb99cf0b419efa2cb8d7fdf2e71f6634
new file mode 100644
index 0000000..00d6aa2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9eb50c5eb99cf0b419efa2cb8d7fdf2e71f6634
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ba46bf502f75c1e66fb89e18c270da8e5a62207f b/test/core/end2end/fuzzers/api_fuzzer_corpus/ba46bf502f75c1e66fb89e18c270da8e5a62207f
new file mode 100644
index 0000000..44f9cd9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ba46bf502f75c1e66fb89e18c270da8e5a62207f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bb74226288b9d3a163029a25857bbebe84227222 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb74226288b9d3a163029a25857bbebe84227222
new file mode 100644
index 0000000..bf7879e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb74226288b9d3a163029a25857bbebe84227222
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bdfa6991c33f312c46ac27bdd8089be1670f0ac2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bdfa6991c33f312c46ac27bdd8089be1670f0ac2
new file mode 100644
index 0000000..2c7c25c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bdfa6991c33f312c46ac27bdd8089be1670f0ac2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bf5923216eb069edaf4e135ab7ee426c04d99a25 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bf5923216eb069edaf4e135ab7ee426c04d99a25
new file mode 100644
index 0000000..f1363ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bf5923216eb069edaf4e135ab7ee426c04d99a25
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c09288284e4859b8a85421b19d3c6d0109cdab08 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c09288284e4859b8a85421b19d3c6d0109cdab08
new file mode 100644
index 0000000..e56b7a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c09288284e4859b8a85421b19d3c6d0109cdab08
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c77bd1e9d9be2b6d1362cbb15f63cf749aa113ea b/test/core/end2end/fuzzers/api_fuzzer_corpus/c77bd1e9d9be2b6d1362cbb15f63cf749aa113ea
new file mode 100644
index 0000000..d56d793
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c77bd1e9d9be2b6d1362cbb15f63cf749aa113ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c845faac6d4b713a232aa3a6749afdf4e58d7f6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/c845faac6d4b713a232aa3a6749afdf4e58d7f6a
new file mode 100644
index 0000000..9bf4b96
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c845faac6d4b713a232aa3a6749afdf4e58d7f6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b5d9fdb7ade3538abb794a3231d5777a1640a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b5d9fdb7ade3538abb794a3231d5777a1640a4
new file mode 100644
index 0000000..51af2b7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b5d9fdb7ade3538abb794a3231d5777a1640a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ca5a1e4fccc55aa977b841d8d67e6991a4371860 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca5a1e4fccc55aa977b841d8d67e6991a4371860
new file mode 100644
index 0000000..6b34269
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ca5a1e4fccc55aa977b841d8d67e6991a4371860
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4272fec464c45438dce72eb9381971ed0207de b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4272fec464c45438dce72eb9381971ed0207de
new file mode 100644
index 0000000..949e154
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4272fec464c45438dce72eb9381971ed0207de
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd7cf401276531cea7e4221f249f527f231a5bcb b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd7cf401276531cea7e4221f249f527f231a5bcb
new file mode 100644
index 0000000..603c379
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd7cf401276531cea7e4221f249f527f231a5bcb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cea57d6a128cc7cd195cb2390bfde28047d6acf8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cea57d6a128cc7cd195cb2390bfde28047d6acf8
new file mode 100644
index 0000000..97dcc4f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cea57d6a128cc7cd195cb2390bfde28047d6acf8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-40e0fcf83e934a4ea2d31c009e9dfc1e68f11f3a b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-40e0fcf83e934a4ea2d31c009e9dfc1e68f11f3a
new file mode 100644
index 0000000..63b1a91
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-40e0fcf83e934a4ea2d31c009e9dfc1e68f11f3a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d02fb86e7e236a2253a2eadb0599f5dc261e4048 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d02fb86e7e236a2253a2eadb0599f5dc261e4048
new file mode 100644
index 0000000..f73c109
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d02fb86e7e236a2253a2eadb0599f5dc261e4048
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d07965987a51541498871433e0fc6313884569d3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d07965987a51541498871433e0fc6313884569d3
new file mode 100644
index 0000000..6106a4e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d07965987a51541498871433e0fc6313884569d3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d19a252c00c74403389fe9e057cffeee39a4d2e0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d19a252c00c74403389fe9e057cffeee39a4d2e0
new file mode 100644
index 0000000..964a500
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d19a252c00c74403389fe9e057cffeee39a4d2e0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d1d35a1d2148c62c6021479d4153e65511b33cc1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1d35a1d2148c62c6021479d4153e65511b33cc1
new file mode 100644
index 0000000..2f0696b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d1d35a1d2148c62c6021479d4153e65511b33cc1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d29cf6979d8d58b4cb779a629ebee62d7e42fc9b b/test/core/end2end/fuzzers/api_fuzzer_corpus/d29cf6979d8d58b4cb779a629ebee62d7e42fc9b
new file mode 100644
index 0000000..b6daf76
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d29cf6979d8d58b4cb779a629ebee62d7e42fc9b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d425e534ec074932b5cf4dc9a6cf4fc0683fd690 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d425e534ec074932b5cf4dc9a6cf4fc0683fd690
new file mode 100644
index 0000000..5c8828e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d425e534ec074932b5cf4dc9a6cf4fc0683fd690
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d5d704fdb985efb36fb42f9ee8482ae473bb4695 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5d704fdb985efb36fb42f9ee8482ae473bb4695
new file mode 100644
index 0000000..ca82ab4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5d704fdb985efb36fb42f9ee8482ae473bb4695
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d6d7dc448cc24272ce216dbc7365ebe6e6b7b367 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d6d7dc448cc24272ce216dbc7365ebe6e6b7b367
new file mode 100644
index 0000000..e49fe7d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d6d7dc448cc24272ce216dbc7365ebe6e6b7b367
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d85482b6a40d7edee97709df0ed02558dca4c079 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d85482b6a40d7edee97709df0ed02558dca4c079
new file mode 100644
index 0000000..58e2ed8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d85482b6a40d7edee97709df0ed02558dca4c079
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d8f08b0e061e86e94650aa16f99cae81cd696ca3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8f08b0e061e86e94650aa16f99cae81cd696ca3
new file mode 100644
index 0000000..4c34fd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d8f08b0e061e86e94650aa16f99cae81cd696ca3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dbcaf0a6bd4960e8d0c518494b89bd9b941cfc8e b/test/core/end2end/fuzzers/api_fuzzer_corpus/dbcaf0a6bd4960e8d0c518494b89bd9b941cfc8e
new file mode 100644
index 0000000..098cfa2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dbcaf0a6bd4960e8d0c518494b89bd9b941cfc8e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ddc34d5e97ac12572e6c39a336d219d91fa992b1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddc34d5e97ac12572e6c39a336d219d91fa992b1
new file mode 100644
index 0000000..1b5ebce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddc34d5e97ac12572e6c39a336d219d91fa992b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ddf932a29b8250746ec310af224f95d4a51cb745 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddf932a29b8250746ec310af224f95d4a51cb745
new file mode 100644
index 0000000..62ba3d5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddf932a29b8250746ec310af224f95d4a51cb745
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e16a0f378b50b28dae4458b795c8c80cf869901a b/test/core/end2end/fuzzers/api_fuzzer_corpus/e16a0f378b50b28dae4458b795c8c80cf869901a
new file mode 100644
index 0000000..01296fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e16a0f378b50b28dae4458b795c8c80cf869901a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e18816dbe46249fb0160b8f06c2b71f6943d3d21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e18816dbe46249fb0160b8f06c2b71f6943d3d21
new file mode 100644
index 0000000..d389968
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e18816dbe46249fb0160b8f06c2b71f6943d3d21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e7d4357e2c3ac4db7a9bfece1549f0664e4d317b b/test/core/end2end/fuzzers/api_fuzzer_corpus/e7d4357e2c3ac4db7a9bfece1549f0664e4d317b
new file mode 100644
index 0000000..76cac15
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e7d4357e2c3ac4db7a9bfece1549f0664e4d317b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e8b1814f9a0942322aeb190ae0ad35105784e101 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8b1814f9a0942322aeb190ae0ad35105784e101
new file mode 100644
index 0000000..bb11018
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8b1814f9a0942322aeb190ae0ad35105784e101
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e8bc4c1b1ffb23de5af2c8fe20599c05f94567ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8bc4c1b1ffb23de5af2c8fe20599c05f94567ad
new file mode 100644
index 0000000..8dcd24e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e8bc4c1b1ffb23de5af2c8fe20599c05f94567ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ea421a728134ad3a95a32f081c2bafa9d989836f b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea421a728134ad3a95a32f081c2bafa9d989836f
new file mode 100644
index 0000000..d44736f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ea421a728134ad3a95a32f081c2bafa9d989836f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eab5589ebcdd4596996f0a6de6408a0f3e13437b b/test/core/end2end/fuzzers/api_fuzzer_corpus/eab5589ebcdd4596996f0a6de6408a0f3e13437b
new file mode 100644
index 0000000..733f49c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eab5589ebcdd4596996f0a6de6408a0f3e13437b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec56dad56975e8279b2b229288dff3bb0ceaf661 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec56dad56975e8279b2b229288dff3bb0ceaf661
new file mode 100644
index 0000000..c3a9711
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec56dad56975e8279b2b229288dff3bb0ceaf661
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ed913deced10ab045fe04c783f6a0e2678f1929f b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed913deced10ab045fe04c783f6a0e2678f1929f
new file mode 100644
index 0000000..53b246b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed913deced10ab045fe04c783f6a0e2678f1929f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da
new file mode 100644
index 0000000..abaf0fb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f060953b52fe245eb88ee13b32a3971eaa11e40a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f060953b52fe245eb88ee13b32a3971eaa11e40a
new file mode 100644
index 0000000..b8344c2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f060953b52fe245eb88ee13b32a3971eaa11e40a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f2ee773064f643871134a017d35fd5d8ae74d35c b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2ee773064f643871134a017d35fd5d8ae74d35c
new file mode 100644
index 0000000..eea0435
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2ee773064f643871134a017d35fd5d8ae74d35c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f38d6347f6044dbc3978ef7e5d5adfb7fc8aceb9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f38d6347f6044dbc3978ef7e5d5adfb7fc8aceb9
new file mode 100644
index 0000000..28ed5bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f38d6347f6044dbc3978ef7e5d5adfb7fc8aceb9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f4b66d285bd0328e511625b1c696662a0b0b2e70 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4b66d285bd0328e511625b1c696662a0b0b2e70
new file mode 100644
index 0000000..b3e38df
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f4b66d285bd0328e511625b1c696662a0b0b2e70
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f6d8d78857d868c2f477da7506a1976354f2631d b/test/core/end2end/fuzzers/api_fuzzer_corpus/f6d8d78857d868c2f477da7506a1976354f2631d
new file mode 100644
index 0000000..86ded50
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f6d8d78857d868c2f477da7506a1976354f2631d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb263a744a6d40e183e84ec8a81ca13859c8b5ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb263a744a6d40e183e84ec8a81ca13859c8b5ce
new file mode 100644
index 0000000..97aedba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb263a744a6d40e183e84ec8a81ca13859c8b5ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb324303c6d5819d6f353f78d087e29adba51836 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb324303c6d5819d6f353f78d087e29adba51836
new file mode 100644
index 0000000..0316705
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb324303c6d5819d6f353f78d087e29adba51836
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fbc7dd3fbb6abc462ab0493bfe3a8505f12fe4a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fbc7dd3fbb6abc462ab0493bfe3a8505f12fe4a5
new file mode 100644
index 0000000..e2bb451
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fbc7dd3fbb6abc462ab0493bfe3a8505f12fe4a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fcc42c56cb8847716474703b5a650f41dce98b38 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fcc42c56cb8847716474703b5a650f41dce98b38
new file mode 100644
index 0000000..095375a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fcc42c56cb8847716474703b5a650f41dce98b38
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ff7f9df969df7fe6c9c1515528404b55f9d237b6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff7f9df969df7fe6c9c1515528404b55f9d237b6
new file mode 100644
index 0000000..ca8dccd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ff7f9df969df7fe6c9c1515528404b55f9d237b6
Binary files differ
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index 3266793..67cc24c 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -46,8 +46,9 @@
 
 static gpr_mu g_mu;
 static int g_resolve_port = -1;
-static grpc_resolved_addresses *(*iomgr_resolve_address)(
-    const char *name, const char *default_port);
+static grpc_error *(*iomgr_resolve_address)(const char *name,
+                                            const char *default_port,
+                                            grpc_resolved_addresses **addrs);
 
 static void set_resolve_port(int port) {
   gpr_mu_lock(&g_mu);
@@ -55,28 +56,28 @@
   gpr_mu_unlock(&g_mu);
 }
 
-static grpc_resolved_addresses *my_resolve_address(const char *name,
-                                                   const char *addr) {
+static grpc_error *my_resolve_address(const char *name, const char *addr,
+                                      grpc_resolved_addresses **addrs) {
   if (0 != strcmp(name, "test")) {
-    return iomgr_resolve_address(name, addr);
+    return iomgr_resolve_address(name, addr, addrs);
   }
 
   gpr_mu_lock(&g_mu);
   if (g_resolve_port < 0) {
     gpr_mu_unlock(&g_mu);
-    return NULL;
+    return GRPC_ERROR_CREATE("Forced Failure");
   } else {
-    grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
-    addrs->naddrs = 1;
-    addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
-    memset(addrs->addrs, 0, sizeof(*addrs->addrs));
-    struct sockaddr_in *sa = (struct sockaddr_in *)addrs->addrs[0].addr;
+    *addrs = gpr_malloc(sizeof(**addrs));
+    (*addrs)->naddrs = 1;
+    (*addrs)->addrs = gpr_malloc(sizeof(*(*addrs)->addrs));
+    memset((*addrs)->addrs, 0, sizeof(*(*addrs)->addrs));
+    struct sockaddr_in *sa = (struct sockaddr_in *)(*addrs)->addrs[0].addr;
     sa->sin_family = AF_INET;
     sa->sin_addr.s_addr = htonl(0x7f000001);
     sa->sin_port = htons((uint16_t)g_resolve_port);
-    addrs->addrs[0].len = sizeof(*sa);
+    (*addrs)->addrs[0].len = sizeof(*sa);
     gpr_mu_unlock(&g_mu);
-    return addrs;
+    return GRPC_ERROR_NONE;
   }
 }
 
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index e6edb21..526c05c 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -176,7 +176,7 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
-  GPR_ASSERT(0 == strcmp(details, "Random failure that's not preventable."));
+  GPR_ASSERT(0 == strcmp(details, "Failure that's not preventable."));
 
   gpr_free(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -203,20 +203,23 @@
 
 typedef struct { uint8_t unused; } channel_data;
 
-static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void recv_im_ready(grpc_exec_ctx *exec_ctx, void *arg,
+                          grpc_error *error) {
   grpc_call_element *elem = arg;
   call_data *calld = elem->call_data;
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     // close the stream with an error.
     gpr_slice message =
-        gpr_slice_from_copied_string("Random failure that's not preventable.");
+        gpr_slice_from_copied_string("Failure that's not preventable.");
     grpc_transport_stream_op op;
     memset(&op, 0, sizeof(op));
     grpc_transport_stream_op_add_close(&op, GRPC_STATUS_PERMISSION_DENIED,
                                        &message);
     grpc_call_next_op(exec_ctx, elem, &op);
   }
-  calld->recv_im_ready->cb(exec_ctx, calld->recv_im_ready->cb_arg, false);
+  grpc_exec_ctx_sched(
+      exec_ctx, calld->recv_im_ready,
+      GRPC_ERROR_CREATE_REFERENCING("Forced call to close", &error, 1), NULL);
 }
 
 static void start_transport_stream_op(grpc_exec_ctx *exec_ctx,
diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c
index 6c27ea2..38b32a3 100644
--- a/test/core/http/httpcli_test.c
+++ b/test/core/http/httpcli_test.c
@@ -54,19 +54,20 @@
   return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
 }
 
-static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
-                      const grpc_httpcli_response *response) {
+static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   const char *expect =
       "<html><head><title>Hello world!</title></head>"
       "<body><p>This is a test</p></body></html>";
-  GPR_ASSERT(arg == (void *)42);
+  grpc_http_response *response = arg;
   GPR_ASSERT(response);
   GPR_ASSERT(response->status == 200);
   GPR_ASSERT(response->body_length == strlen(expect));
   GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
   gpr_mu_lock(g_mu);
   g_done = 1;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&g_pops), NULL);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&g_pops), NULL)));
   gpr_mu_unlock(g_mu);
 }
 
@@ -86,19 +87,25 @@
   req.http.path = "/get";
   req.handshaker = &grpc_httpcli_plaintext;
 
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
   grpc_httpcli_get(&exec_ctx, &g_context, &g_pops, &req, n_seconds_time(15),
-                   on_finish, (void *)42);
+                   grpc_closure_create(on_finish, &response), &response);
   gpr_mu_lock(g_mu);
   while (!g_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
+                          &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                          n_seconds_time(20))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
   }
   gpr_mu_unlock(g_mu);
   gpr_free(host);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_post(int port) {
@@ -117,22 +124,29 @@
   req.http.path = "/post";
   req.handshaker = &grpc_httpcli_plaintext;
 
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
   grpc_httpcli_post(&exec_ctx, &g_context, &g_pops, &req, "hello", 5,
-                    n_seconds_time(15), on_finish, (void *)42);
+                    n_seconds_time(15),
+                    grpc_closure_create(on_finish, &response), &response);
   gpr_mu_lock(g_mu);
   while (!g_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
+                          &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                          n_seconds_time(20))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
   }
   gpr_mu_unlock(g_mu);
   gpr_free(host);
+  grpc_http_response_destroy(&response);
 }
 
-static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
   grpc_pollset_destroy(grpc_polling_entity_pollset(p));
 }
 
diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c
index 1b0bc60..359e557 100644
--- a/test/core/http/httpscli_test.c
+++ b/test/core/http/httpscli_test.c
@@ -54,19 +54,20 @@
   return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
 }
 
-static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
-                      const grpc_httpcli_response *response) {
+static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   const char *expect =
       "<html><head><title>Hello world!</title></head>"
       "<body><p>This is a test</p></body></html>";
-  GPR_ASSERT(arg == (void *)42);
+  grpc_http_response *response = arg;
   GPR_ASSERT(response);
   GPR_ASSERT(response->status == 200);
   GPR_ASSERT(response->body_length == strlen(expect));
   GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
   gpr_mu_lock(g_mu);
   g_done = 1;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&g_pops), NULL);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&g_pops), NULL)));
   gpr_mu_unlock(g_mu);
 }
 
@@ -87,19 +88,25 @@
   req.http.path = "/get";
   req.handshaker = &grpc_httpcli_ssl;
 
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
   grpc_httpcli_get(&exec_ctx, &g_context, &g_pops, &req, n_seconds_time(15),
-                   on_finish, (void *)42);
+                   grpc_closure_create(on_finish, &response), &response);
   gpr_mu_lock(g_mu);
   while (!g_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
+                          &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                          n_seconds_time(20))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
   }
   gpr_mu_unlock(g_mu);
   gpr_free(host);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_post(int port) {
@@ -119,22 +126,29 @@
   req.http.path = "/post";
   req.handshaker = &grpc_httpcli_ssl;
 
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
   grpc_httpcli_post(&exec_ctx, &g_context, &g_pops, &req, "hello", 5,
-                    n_seconds_time(15), on_finish, (void *)42);
+                    n_seconds_time(15),
+                    grpc_closure_create(on_finish, &response), &response);
   gpr_mu_lock(g_mu);
   while (!g_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
+                          &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                          n_seconds_time(20))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
   }
   gpr_mu_unlock(g_mu);
   gpr_free(host);
+  grpc_http_response_destroy(&response);
 }
 
-static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
   grpc_pollset_destroy(grpc_polling_entity_pollset(p));
 }
 
diff --git a/test/core/http/parser_test.c b/test/core/http/parser_test.c
index 7fdf60c..d645d28 100644
--- a/test/core/http/parser_test.c
+++ b/test/core/http/parser_test.c
@@ -44,38 +44,39 @@
 #include "test/core/util/test_config.h"
 
 static void test_request_succeeds(grpc_slice_split_mode split_mode,
-                                  char *request, char *expect_method,
+                                  char *request_text, char *expect_method,
                                   grpc_http_version expect_version,
                                   char *expect_path, char *expect_body, ...) {
   grpc_http_parser parser;
-  gpr_slice input_slice = gpr_slice_from_copied_string(request);
+  gpr_slice input_slice = gpr_slice_from_copied_string(request_text);
   size_t num_slices;
   size_t i;
   gpr_slice *slices;
   va_list args;
+  grpc_http_request request;
+  memset(&request, 0, sizeof(request));
 
   grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
   gpr_slice_unref(input_slice);
 
-  grpc_http_parser_init(&parser);
+  grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
 
   for (i = 0; i < num_slices; i++) {
-    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]));
+    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]) == GRPC_ERROR_NONE);
     gpr_slice_unref(slices[i]);
   }
-  GPR_ASSERT(grpc_http_parser_eof(&parser));
+  GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE);
 
   GPR_ASSERT(GRPC_HTTP_REQUEST == parser.type);
-  GPR_ASSERT(0 == strcmp(expect_method, parser.http.request.method));
-  GPR_ASSERT(0 == strcmp(expect_path, parser.http.request.path));
-  GPR_ASSERT(expect_version == parser.http.request.version);
+  GPR_ASSERT(0 == strcmp(expect_method, request.method));
+  GPR_ASSERT(0 == strcmp(expect_path, request.path));
+  GPR_ASSERT(expect_version == request.version);
 
   if (expect_body != NULL) {
-    GPR_ASSERT(strlen(expect_body) == parser.http.request.body_length);
-    GPR_ASSERT(0 == memcmp(expect_body, parser.http.request.body,
-                           parser.http.request.body_length));
+    GPR_ASSERT(strlen(expect_body) == request.body_length);
+    GPR_ASSERT(0 == memcmp(expect_body, request.body, request.body_length));
   } else {
-    GPR_ASSERT(parser.http.request.body_length == 0);
+    GPR_ASSERT(request.body_length == 0);
   }
 
   va_start(args, expect_body);
@@ -85,48 +86,50 @@
     char *expect_value;
     expect_key = va_arg(args, char *);
     if (!expect_key) break;
-    GPR_ASSERT(i < parser.http.request.hdr_count);
+    GPR_ASSERT(i < request.hdr_count);
     expect_value = va_arg(args, char *);
     GPR_ASSERT(expect_value);
-    GPR_ASSERT(0 == strcmp(expect_key, parser.http.request.hdrs[i].key));
-    GPR_ASSERT(0 == strcmp(expect_value, parser.http.request.hdrs[i].value));
+    GPR_ASSERT(0 == strcmp(expect_key, request.hdrs[i].key));
+    GPR_ASSERT(0 == strcmp(expect_value, request.hdrs[i].value));
     i++;
   }
   va_end(args);
-  GPR_ASSERT(i == parser.http.request.hdr_count);
+  GPR_ASSERT(i == request.hdr_count);
 
+  grpc_http_request_destroy(&request);
   grpc_http_parser_destroy(&parser);
   gpr_free(slices);
 }
 
-static void test_succeeds(grpc_slice_split_mode split_mode, char *response,
+static void test_succeeds(grpc_slice_split_mode split_mode, char *response_text,
                           int expect_status, char *expect_body, ...) {
   grpc_http_parser parser;
-  gpr_slice input_slice = gpr_slice_from_copied_string(response);
+  gpr_slice input_slice = gpr_slice_from_copied_string(response_text);
   size_t num_slices;
   size_t i;
   gpr_slice *slices;
   va_list args;
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
 
   grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
   gpr_slice_unref(input_slice);
 
-  grpc_http_parser_init(&parser);
+  grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
 
   for (i = 0; i < num_slices; i++) {
-    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]));
+    GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]) == GRPC_ERROR_NONE);
     gpr_slice_unref(slices[i]);
   }
-  GPR_ASSERT(grpc_http_parser_eof(&parser));
+  GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE);
 
   GPR_ASSERT(GRPC_HTTP_RESPONSE == parser.type);
-  GPR_ASSERT(expect_status == parser.http.response.status);
+  GPR_ASSERT(expect_status == response.status);
   if (expect_body != NULL) {
-    GPR_ASSERT(strlen(expect_body) == parser.http.response.body_length);
-    GPR_ASSERT(0 == memcmp(expect_body, parser.http.response.body,
-                           parser.http.response.body_length));
+    GPR_ASSERT(strlen(expect_body) == response.body_length);
+    GPR_ASSERT(0 == memcmp(expect_body, response.body, response.body_length));
   } else {
-    GPR_ASSERT(parser.http.response.body_length == 0);
+    GPR_ASSERT(response.body_length == 0);
   }
 
   va_start(args, expect_body);
@@ -136,77 +139,84 @@
     char *expect_value;
     expect_key = va_arg(args, char *);
     if (!expect_key) break;
-    GPR_ASSERT(i < parser.http.response.hdr_count);
+    GPR_ASSERT(i < response.hdr_count);
     expect_value = va_arg(args, char *);
     GPR_ASSERT(expect_value);
-    GPR_ASSERT(0 == strcmp(expect_key, parser.http.response.hdrs[i].key));
-    GPR_ASSERT(0 == strcmp(expect_value, parser.http.response.hdrs[i].value));
+    GPR_ASSERT(0 == strcmp(expect_key, response.hdrs[i].key));
+    GPR_ASSERT(0 == strcmp(expect_value, response.hdrs[i].value));
     i++;
   }
   va_end(args);
-  GPR_ASSERT(i == parser.http.response.hdr_count);
+  GPR_ASSERT(i == response.hdr_count);
 
+  grpc_http_response_destroy(&response);
   grpc_http_parser_destroy(&parser);
   gpr_free(slices);
 }
 
-static void test_fails(grpc_slice_split_mode split_mode, char *response) {
+static void test_fails(grpc_slice_split_mode split_mode, char *response_text) {
   grpc_http_parser parser;
-  gpr_slice input_slice = gpr_slice_from_copied_string(response);
+  gpr_slice input_slice = gpr_slice_from_copied_string(response_text);
   size_t num_slices;
   size_t i;
   gpr_slice *slices;
-  int done = 0;
+  grpc_error *error = GRPC_ERROR_NONE;
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
 
   grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
   gpr_slice_unref(input_slice);
 
-  grpc_http_parser_init(&parser);
+  grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
 
   for (i = 0; i < num_slices; i++) {
-    if (!done && !grpc_http_parser_parse(&parser, slices[i])) {
-      done = 1;
+    if (GRPC_ERROR_NONE == error) {
+      error = grpc_http_parser_parse(&parser, slices[i]);
     }
     gpr_slice_unref(slices[i]);
   }
-  if (!done && !grpc_http_parser_eof(&parser)) {
-    done = 1;
+  if (GRPC_ERROR_NONE == error) {
+    error = grpc_http_parser_eof(&parser);
   }
-  GPR_ASSERT(done);
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
+  GRPC_ERROR_UNREF(error);
 
+  grpc_http_response_destroy(&response);
   grpc_http_parser_destroy(&parser);
   gpr_free(slices);
 }
 
-static const uint8_t failed_test1[] = {
-    0x9e, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x4a,
-    0x48, 0x54, 0x54, 0x30, 0x32, 0x16, 0xa,  0x2f, 0x48, 0x20,
-    0x31, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x31, 0x54, 0x54, 0xb9,
-    0x32, 0x31, 0x2e, 0x20, 0x32, 0x30, 0x20,
-};
+static void test_request_fails(grpc_slice_split_mode split_mode,
+                               char *request_text) {
+  grpc_http_parser parser;
+  gpr_slice input_slice = gpr_slice_from_copied_string(request_text);
+  size_t num_slices;
+  size_t i;
+  gpr_slice *slices;
+  grpc_error *error = GRPC_ERROR_NONE;
+  grpc_http_request request;
+  memset(&request, 0, sizeof(request));
 
-typedef struct {
-  const char *name;
-  const uint8_t *data;
-  size_t length;
-} failed_test;
+  grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
+  gpr_slice_unref(input_slice);
 
-#define FAILED_TEST(name) \
-  { #name, name, sizeof(name) }
+  grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
 
-failed_test failed_tests[] = {
-    FAILED_TEST(failed_test1),
-};
+  for (i = 0; i < num_slices; i++) {
+    if (error == GRPC_ERROR_NONE) {
+      error = grpc_http_parser_parse(&parser, slices[i]);
+    }
+    gpr_slice_unref(slices[i]);
+  }
+  if (error == GRPC_ERROR_NONE) {
+    error = grpc_http_parser_eof(&parser);
+  }
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
+  GRPC_ERROR_UNREF(error);
 
-static void test_doesnt_crash(failed_test t) {
-  gpr_log(GPR_DEBUG, "Run previously failed test: %s", t.name);
-  grpc_http_parser p;
-  grpc_http_parser_init(&p);
-  gpr_slice slice =
-      gpr_slice_from_copied_buffer((const char *)t.data, t.length);
-  grpc_http_parser_parse(&p, slice);
-  gpr_slice_unref(slice);
-  grpc_http_parser_destroy(&p);
+  grpc_http_request_destroy(&request);
+  grpc_http_parser_destroy(&parser);
+  gpr_free(slices);
 }
 
 int main(int argc, char **argv) {
@@ -217,10 +227,6 @@
 
   grpc_test_init(argc, argv);
 
-  for (i = 0; i < GPR_ARRAY_SIZE(failed_tests); i++) {
-    test_doesnt_crash(failed_tests[i]);
-  }
-
   for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) {
     test_succeeds(split_modes[i],
                   "HTTP/1.0 200 OK\r\n"
@@ -286,12 +292,12 @@
                "  def\r\n"
                "\r\n"
                "hello world!");
-    test_fails(split_modes[i], "GET\r\n");
-    test_fails(split_modes[i], "GET /\r\n");
-    test_fails(split_modes[i], "GET / HTTP/0.0\r\n");
-    test_fails(split_modes[i], "GET / ____/1.0\r\n");
-    test_fails(split_modes[i], "GET / HTTP/1.2\r\n");
-    test_fails(split_modes[i], "GET / HTTP/1.0\n");
+    test_request_fails(split_modes[i], "GET\r\n");
+    test_request_fails(split_modes[i], "GET /\r\n");
+    test_request_fails(split_modes[i], "GET / HTTP/0.0\r\n");
+    test_request_fails(split_modes[i], "GET / ____/1.0\r\n");
+    test_request_fails(split_modes[i], "GET / HTTP/1.2\r\n");
+    test_request_fails(split_modes[i], "GET / HTTP/1.0\n");
 
     tmp1 = gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
     memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1);
diff --git a/test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427 b/test/core/http/request_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
similarity index 100%
rename from test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
rename to test/core/http/request_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
diff --git a/test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba b/test/core/http/request_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
similarity index 100%
rename from test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
rename to test/core/http/request_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
diff --git a/test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97 b/test/core/http/request_corpus/069352518a1d1baa05f317c677d275cefda2ac97
similarity index 100%
rename from test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97
rename to test/core/http/request_corpus/069352518a1d1baa05f317c677d275cefda2ac97
diff --git a/test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34 b/test/core/http/request_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
similarity index 100%
rename from test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
rename to test/core/http/request_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
diff --git a/test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d b/test/core/http/request_corpus/0c5b7c2569410b526605e308309a7f36574e530d
similarity index 100%
rename from test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d
rename to test/core/http/request_corpus/0c5b7c2569410b526605e308309a7f36574e530d
Binary files differ
diff --git a/test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf b/test/core/http/request_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
similarity index 100%
rename from test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
rename to test/core/http/request_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
diff --git a/test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4 b/test/core/http/request_corpus/1e1273f90187fdf5df3625764245610f86af6aa4
similarity index 100%
rename from test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4
rename to test/core/http/request_corpus/1e1273f90187fdf5df3625764245610f86af6aa4
diff --git a/test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55 b/test/core/http/request_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
similarity index 100%
rename from test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
rename to test/core/http/request_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
diff --git a/test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f b/test/core/http/request_corpus/24756c396bc72894fd720092bb6f9c03e66b469f
similarity index 100%
rename from test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f
rename to test/core/http/request_corpus/24756c396bc72894fd720092bb6f9c03e66b469f
diff --git a/test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f b/test/core/http/request_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
similarity index 100%
rename from test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
rename to test/core/http/request_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
Binary files differ
diff --git a/test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9 b/test/core/http/request_corpus/29daa75432381937fd005cb25e314e328de6e9f9
similarity index 100%
rename from test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9
rename to test/core/http/request_corpus/29daa75432381937fd005cb25e314e328de6e9f9
diff --git a/test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc b/test/core/http/request_corpus/2a75204bc492084ad853682f8de3fb137d5907bc
similarity index 100%
rename from test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc
rename to test/core/http/request_corpus/2a75204bc492084ad853682f8de3fb137d5907bc
diff --git a/test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305 b/test/core/http/request_corpus/2d34ba249b755a880525cf53c665633a5e359305
similarity index 100%
rename from test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305
rename to test/core/http/request_corpus/2d34ba249b755a880525cf53c665633a5e359305
Binary files differ
diff --git a/test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2 b/test/core/http/request_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
similarity index 100%
rename from test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
rename to test/core/http/request_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
diff --git a/test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b b/test/core/http/request_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
similarity index 100%
rename from test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
rename to test/core/http/request_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
diff --git a/test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece b/test/core/http/request_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
similarity index 100%
rename from test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
rename to test/core/http/request_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
diff --git a/test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf b/test/core/http/request_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
similarity index 100%
rename from test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
rename to test/core/http/request_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
Binary files differ
diff --git a/test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d b/test/core/http/request_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
similarity index 100%
rename from test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
rename to test/core/http/request_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
Binary files differ
diff --git a/test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76 b/test/core/http/request_corpus/39b19c41ba537f37511eff7727733715db432e76
similarity index 100%
rename from test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76
rename to test/core/http/request_corpus/39b19c41ba537f37511eff7727733715db432e76
diff --git a/test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac b/test/core/http/request_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
similarity index 100%
rename from test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
rename to test/core/http/request_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
diff --git a/test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b b/test/core/http/request_corpus/3f03265921120c6ffa61b944e213e062a5538d4b
similarity index 100%
rename from test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b
rename to test/core/http/request_corpus/3f03265921120c6ffa61b944e213e062a5538d4b
diff --git a/test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046 b/test/core/http/request_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
similarity index 100%
rename from test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
rename to test/core/http/request_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
diff --git a/test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9 b/test/core/http/request_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
similarity index 100%
rename from test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
rename to test/core/http/request_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
Binary files differ
diff --git a/test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa b/test/core/http/request_corpus/487725eb38511c79a9340bf4560a1411061fa6fa
similarity index 100%
rename from test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa
rename to test/core/http/request_corpus/487725eb38511c79a9340bf4560a1411061fa6fa
diff --git a/test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5 b/test/core/http/request_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
similarity index 100%
rename from test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
rename to test/core/http/request_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
diff --git a/test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55 b/test/core/http/request_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
similarity index 100%
rename from test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
rename to test/core/http/request_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
diff --git a/test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d b/test/core/http/request_corpus/5028c56a5116a186b7343ff59567b47347a0796d
similarity index 100%
rename from test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d
rename to test/core/http/request_corpus/5028c56a5116a186b7343ff59567b47347a0796d
diff --git a/test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff b/test/core/http/request_corpus/533f62b3f495ce704babf3ee8d840f196a714dff
similarity index 100%
rename from test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff
rename to test/core/http/request_corpus/533f62b3f495ce704babf3ee8d840f196a714dff
diff --git a/test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104 b/test/core/http/request_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
similarity index 100%
rename from test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
rename to test/core/http/request_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
diff --git a/test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee b/test/core/http/request_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
similarity index 100%
rename from test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
rename to test/core/http/request_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
Binary files differ
diff --git a/test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5 b/test/core/http/request_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
similarity index 100%
rename from test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
rename to test/core/http/request_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
diff --git a/test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0 b/test/core/http/request_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
similarity index 100%
rename from test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
rename to test/core/http/request_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
diff --git a/test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e b/test/core/http/request_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
similarity index 100%
rename from test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
rename to test/core/http/request_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
Binary files differ
diff --git a/test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2 b/test/core/http/request_corpus/657368df512ca6294b9df16adf935a3f374a8be2
similarity index 100%
rename from test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2
rename to test/core/http/request_corpus/657368df512ca6294b9df16adf935a3f374a8be2
diff --git a/test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337 b/test/core/http/request_corpus/7fc4520094902ce2c760d70eaad5b674d2817337
similarity index 100%
rename from test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337
rename to test/core/http/request_corpus/7fc4520094902ce2c760d70eaad5b674d2817337
diff --git a/test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6 b/test/core/http/request_corpus/81f59a12b458ec3604035cb962165c604d1355e6
similarity index 100%
rename from test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6
rename to test/core/http/request_corpus/81f59a12b458ec3604035cb962165c604d1355e6
diff --git a/test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9 b/test/core/http/request_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
similarity index 100%
rename from test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
rename to test/core/http/request_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
diff --git a/test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c b/test/core/http/request_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
similarity index 100%
rename from test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
rename to test/core/http/request_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
Binary files differ
diff --git a/test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548 b/test/core/http/request_corpus/97e4499d450c95660de86747f527e670f2012548
similarity index 100%
rename from test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548
rename to test/core/http/request_corpus/97e4499d450c95660de86747f527e670f2012548
diff --git a/test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1 b/test/core/http/request_corpus/9a996857196e0998a1278994a9bab3d35526e7f1
similarity index 100%
rename from test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1
rename to test/core/http/request_corpus/9a996857196e0998a1278994a9bab3d35526e7f1
diff --git a/test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8 b/test/core/http/request_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
similarity index 100%
rename from test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
rename to test/core/http/request_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
diff --git a/test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1 b/test/core/http/request_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
similarity index 100%
rename from test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
rename to test/core/http/request_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
diff --git a/test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85 b/test/core/http/request_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
similarity index 100%
rename from test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
rename to test/core/http/request_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
diff --git a/test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441 b/test/core/http/request_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
similarity index 100%
rename from test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
rename to test/core/http/request_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
diff --git a/test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0 b/test/core/http/request_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
similarity index 100%
rename from test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
rename to test/core/http/request_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
Binary files differ
diff --git a/test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47 b/test/core/http/request_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
similarity index 100%
rename from test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
rename to test/core/http/request_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
diff --git a/test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940 b/test/core/http/request_corpus/c4acff8aa2ff886f35439f72625d05002990c940
similarity index 100%
rename from test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940
rename to test/core/http/request_corpus/c4acff8aa2ff886f35439f72625d05002990c940
diff --git a/test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8 b/test/core/http/request_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
similarity index 100%
rename from test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
rename to test/core/http/request_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
diff --git a/test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2 b/test/core/http/request_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
similarity index 100%
rename from test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
rename to test/core/http/request_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
diff --git a/test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70 b/test/core/http/request_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
similarity index 100%
rename from test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
rename to test/core/http/request_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
diff --git a/test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa b/test/core/http/request_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
similarity index 100%
rename from test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
rename to test/core/http/request_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
Binary files differ
diff --git a/test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453 b/test/core/http/request_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
similarity index 100%
rename from test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
rename to test/core/http/request_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
diff --git a/test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629 b/test/core/http/request_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
similarity index 100%
rename from test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
rename to test/core/http/request_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
diff --git a/test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4 b/test/core/http/request_corpus/d936dad71c129cf659097dc3db64550c4dd467f4
similarity index 100%
rename from test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4
rename to test/core/http/request_corpus/d936dad71c129cf659097dc3db64550c4dd467f4
diff --git a/test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b b/test/core/http/request_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
similarity index 100%
rename from test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
rename to test/core/http/request_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
diff --git a/test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089 b/test/core/http/request_corpus/e5c364b205855a2991ce07482aebb2a3a6147089
similarity index 100%
rename from test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089
rename to test/core/http/request_corpus/e5c364b205855a2991ce07482aebb2a3a6147089
diff --git a/test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb b/test/core/http/request_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
similarity index 100%
rename from test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
rename to test/core/http/request_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
diff --git a/test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066 b/test/core/http/request_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
similarity index 100%
rename from test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
rename to test/core/http/request_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
diff --git a/test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b b/test/core/http/request_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
similarity index 100%
rename from test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
rename to test/core/http/request_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
Binary files differ
diff --git a/test/core/http/corpus/request1.txt b/test/core/http/request_corpus/request1.txt
similarity index 100%
rename from test/core/http/corpus/request1.txt
rename to test/core/http/request_corpus/request1.txt
diff --git a/test/core/http/corpus/request2.txt b/test/core/http/request_corpus/request2.txt
similarity index 100%
rename from test/core/http/corpus/request2.txt
rename to test/core/http/request_corpus/request2.txt
diff --git a/test/core/http/corpus/request3.txt b/test/core/http/request_corpus/request3.txt
similarity index 100%
rename from test/core/http/corpus/request3.txt
rename to test/core/http/request_corpus/request3.txt
diff --git a/test/core/http/corpus/request4.txt b/test/core/http/request_corpus/request4.txt
similarity index 100%
rename from test/core/http/corpus/request4.txt
rename to test/core/http/request_corpus/request4.txt
diff --git a/test/core/http/corpus/request5.txt b/test/core/http/request_corpus/request5.txt
similarity index 100%
rename from test/core/http/corpus/request5.txt
rename to test/core/http/request_corpus/request5.txt
diff --git a/test/core/http/corpus/response1.txt b/test/core/http/request_corpus/response1.txt
similarity index 100%
rename from test/core/http/corpus/response1.txt
rename to test/core/http/request_corpus/response1.txt
diff --git a/test/core/http/corpus/response2.txt b/test/core/http/request_corpus/response2.txt
similarity index 100%
rename from test/core/http/corpus/response2.txt
rename to test/core/http/request_corpus/response2.txt
diff --git a/test/core/http/corpus/response3.txt b/test/core/http/request_corpus/response3.txt
similarity index 100%
rename from test/core/http/corpus/response3.txt
rename to test/core/http/request_corpus/response3.txt
diff --git a/test/core/http/corpus/response4.txt b/test/core/http/request_corpus/response4.txt
similarity index 100%
rename from test/core/http/corpus/response4.txt
rename to test/core/http/request_corpus/response4.txt
diff --git a/test/core/http/corpus/response5.txt b/test/core/http/request_corpus/response5.txt
similarity index 100%
rename from test/core/http/corpus/response5.txt
rename to test/core/http/request_corpus/response5.txt
diff --git a/test/core/http/corpus/response6.txt b/test/core/http/request_corpus/response6.txt
similarity index 100%
rename from test/core/http/corpus/response6.txt
rename to test/core/http/request_corpus/response6.txt
diff --git a/test/core/http/corpus/toolong.txt b/test/core/http/request_corpus/toolong.txt
similarity index 100%
rename from test/core/http/corpus/toolong.txt
rename to test/core/http/request_corpus/toolong.txt
diff --git a/test/core/http/fuzzer.c b/test/core/http/request_fuzzer.c
similarity index 87%
copy from test/core/http/fuzzer.c
copy to test/core/http/request_fuzzer.c
index c3c634f..5941401 100644
--- a/test/core/http/fuzzer.c
+++ b/test/core/http/request_fuzzer.c
@@ -44,11 +44,14 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   grpc_http_parser parser;
-  grpc_http_parser_init(&parser);
+  grpc_http_request request;
+  memset(&request, 0, sizeof(request));
+  grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
   gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
-  grpc_http_parser_parse(&parser, slice);
-  grpc_http_parser_eof(&parser);
+  GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice));
+  GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser));
   gpr_slice_unref(slice);
   grpc_http_parser_destroy(&parser);
+  grpc_http_request_destroy(&request);
   return 0;
 }
diff --git a/test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427 b/test/core/http/response_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
similarity index 100%
copy from test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
copy to test/core/http/response_corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427
diff --git a/test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba b/test/core/http/response_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
similarity index 100%
copy from test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
copy to test/core/http/response_corpus/05e613853d64a9669ea3cf41b0de777dc24931ba
diff --git a/test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97 b/test/core/http/response_corpus/069352518a1d1baa05f317c677d275cefda2ac97
similarity index 100%
copy from test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97
copy to test/core/http/response_corpus/069352518a1d1baa05f317c677d275cefda2ac97
diff --git a/test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34 b/test/core/http/response_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
similarity index 100%
copy from test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
copy to test/core/http/response_corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34
diff --git a/test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d b/test/core/http/response_corpus/0c5b7c2569410b526605e308309a7f36574e530d
similarity index 100%
copy from test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d
copy to test/core/http/response_corpus/0c5b7c2569410b526605e308309a7f36574e530d
Binary files differ
diff --git a/test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf b/test/core/http/response_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
similarity index 100%
copy from test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
copy to test/core/http/response_corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf
diff --git a/test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4 b/test/core/http/response_corpus/1e1273f90187fdf5df3625764245610f86af6aa4
similarity index 100%
copy from test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4
copy to test/core/http/response_corpus/1e1273f90187fdf5df3625764245610f86af6aa4
diff --git a/test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55 b/test/core/http/response_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
similarity index 100%
copy from test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
copy to test/core/http/response_corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55
diff --git a/test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f b/test/core/http/response_corpus/24756c396bc72894fd720092bb6f9c03e66b469f
similarity index 100%
copy from test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f
copy to test/core/http/response_corpus/24756c396bc72894fd720092bb6f9c03e66b469f
diff --git a/test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f b/test/core/http/response_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
similarity index 100%
copy from test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
copy to test/core/http/response_corpus/276def41311933421ae7a9ee42e906c85b6a4d3f
Binary files differ
diff --git a/test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9 b/test/core/http/response_corpus/29daa75432381937fd005cb25e314e328de6e9f9
similarity index 100%
copy from test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9
copy to test/core/http/response_corpus/29daa75432381937fd005cb25e314e328de6e9f9
diff --git a/test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc b/test/core/http/response_corpus/2a75204bc492084ad853682f8de3fb137d5907bc
similarity index 100%
copy from test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc
copy to test/core/http/response_corpus/2a75204bc492084ad853682f8de3fb137d5907bc
diff --git a/test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305 b/test/core/http/response_corpus/2d34ba249b755a880525cf53c665633a5e359305
similarity index 100%
copy from test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305
copy to test/core/http/response_corpus/2d34ba249b755a880525cf53c665633a5e359305
Binary files differ
diff --git a/test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2 b/test/core/http/response_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
similarity index 100%
copy from test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
copy to test/core/http/response_corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2
diff --git a/test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b b/test/core/http/response_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
similarity index 100%
copy from test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
copy to test/core/http/response_corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b
diff --git a/test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece b/test/core/http/response_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
similarity index 100%
copy from test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
copy to test/core/http/response_corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece
diff --git a/test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf b/test/core/http/response_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
similarity index 100%
copy from test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
copy to test/core/http/response_corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf
Binary files differ
diff --git a/test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d b/test/core/http/response_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
similarity index 100%
copy from test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
copy to test/core/http/response_corpus/3953688866ccb3b4f371f1a858570d6afdb6452d
Binary files differ
diff --git a/test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76 b/test/core/http/response_corpus/39b19c41ba537f37511eff7727733715db432e76
similarity index 100%
copy from test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76
copy to test/core/http/response_corpus/39b19c41ba537f37511eff7727733715db432e76
diff --git a/test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac b/test/core/http/response_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
similarity index 100%
copy from test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
copy to test/core/http/response_corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac
diff --git a/test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b b/test/core/http/response_corpus/3f03265921120c6ffa61b944e213e062a5538d4b
similarity index 100%
copy from test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b
copy to test/core/http/response_corpus/3f03265921120c6ffa61b944e213e062a5538d4b
diff --git a/test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046 b/test/core/http/response_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
similarity index 100%
copy from test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
copy to test/core/http/response_corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046
diff --git a/test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9 b/test/core/http/response_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
similarity index 100%
copy from test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
copy to test/core/http/response_corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9
Binary files differ
diff --git a/test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa b/test/core/http/response_corpus/487725eb38511c79a9340bf4560a1411061fa6fa
similarity index 100%
copy from test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa
copy to test/core/http/response_corpus/487725eb38511c79a9340bf4560a1411061fa6fa
diff --git a/test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5 b/test/core/http/response_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
similarity index 100%
copy from test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
copy to test/core/http/response_corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5
diff --git a/test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55 b/test/core/http/response_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
similarity index 100%
copy from test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
copy to test/core/http/response_corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55
diff --git a/test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d b/test/core/http/response_corpus/5028c56a5116a186b7343ff59567b47347a0796d
similarity index 100%
copy from test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d
copy to test/core/http/response_corpus/5028c56a5116a186b7343ff59567b47347a0796d
diff --git a/test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff b/test/core/http/response_corpus/533f62b3f495ce704babf3ee8d840f196a714dff
similarity index 100%
copy from test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff
copy to test/core/http/response_corpus/533f62b3f495ce704babf3ee8d840f196a714dff
diff --git a/test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104 b/test/core/http/response_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
similarity index 100%
copy from test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
copy to test/core/http/response_corpus/5892cbb284771fc9761caae37b19cd6e27dbc104
diff --git a/test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee b/test/core/http/response_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
similarity index 100%
copy from test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
copy to test/core/http/response_corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee
Binary files differ
diff --git a/test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5 b/test/core/http/response_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
similarity index 100%
copy from test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
copy to test/core/http/response_corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5
diff --git a/test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0 b/test/core/http/response_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
similarity index 100%
copy from test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
copy to test/core/http/response_corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0
diff --git a/test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e b/test/core/http/response_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
similarity index 100%
copy from test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
copy to test/core/http/response_corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e
Binary files differ
diff --git a/test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2 b/test/core/http/response_corpus/657368df512ca6294b9df16adf935a3f374a8be2
similarity index 100%
copy from test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2
copy to test/core/http/response_corpus/657368df512ca6294b9df16adf935a3f374a8be2
diff --git a/test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337 b/test/core/http/response_corpus/7fc4520094902ce2c760d70eaad5b674d2817337
similarity index 100%
copy from test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337
copy to test/core/http/response_corpus/7fc4520094902ce2c760d70eaad5b674d2817337
diff --git a/test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6 b/test/core/http/response_corpus/81f59a12b458ec3604035cb962165c604d1355e6
similarity index 100%
copy from test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6
copy to test/core/http/response_corpus/81f59a12b458ec3604035cb962165c604d1355e6
diff --git a/test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9 b/test/core/http/response_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
similarity index 100%
copy from test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
copy to test/core/http/response_corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9
diff --git a/test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c b/test/core/http/response_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
similarity index 100%
copy from test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
copy to test/core/http/response_corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c
Binary files differ
diff --git a/test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548 b/test/core/http/response_corpus/97e4499d450c95660de86747f527e670f2012548
similarity index 100%
copy from test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548
copy to test/core/http/response_corpus/97e4499d450c95660de86747f527e670f2012548
diff --git a/test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1 b/test/core/http/response_corpus/9a996857196e0998a1278994a9bab3d35526e7f1
similarity index 100%
copy from test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1
copy to test/core/http/response_corpus/9a996857196e0998a1278994a9bab3d35526e7f1
diff --git a/test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8 b/test/core/http/response_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
similarity index 100%
copy from test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
copy to test/core/http/response_corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8
diff --git a/test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1 b/test/core/http/response_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
similarity index 100%
copy from test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
copy to test/core/http/response_corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1
diff --git a/test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85 b/test/core/http/response_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
similarity index 100%
copy from test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
copy to test/core/http/response_corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85
diff --git a/test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441 b/test/core/http/response_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
similarity index 100%
copy from test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
copy to test/core/http/response_corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441
diff --git a/test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0 b/test/core/http/response_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
similarity index 100%
copy from test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
copy to test/core/http/response_corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0
Binary files differ
diff --git a/test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47 b/test/core/http/response_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
similarity index 100%
copy from test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
copy to test/core/http/response_corpus/b04fea5c041c707db0ad9c09a81672557b52cc47
diff --git a/test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940 b/test/core/http/response_corpus/c4acff8aa2ff886f35439f72625d05002990c940
similarity index 100%
copy from test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940
copy to test/core/http/response_corpus/c4acff8aa2ff886f35439f72625d05002990c940
diff --git a/test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8 b/test/core/http/response_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
similarity index 100%
copy from test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
copy to test/core/http/response_corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8
diff --git a/test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2 b/test/core/http/response_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
similarity index 100%
copy from test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
copy to test/core/http/response_corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2
diff --git a/test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70 b/test/core/http/response_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
similarity index 100%
copy from test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
copy to test/core/http/response_corpus/cce734f1b263de6994f7950e0df7bf0c81449f70
diff --git a/test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa b/test/core/http/response_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
similarity index 100%
copy from test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
copy to test/core/http/response_corpus/d39c8ee11a697634a09b309460c0bbd967e7effa
Binary files differ
diff --git a/test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453 b/test/core/http/response_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
similarity index 100%
copy from test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
copy to test/core/http/response_corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453
diff --git a/test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629 b/test/core/http/response_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
similarity index 100%
copy from test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
copy to test/core/http/response_corpus/d51f7fcc089f269c7afecaaca51966bab5fde629
diff --git a/test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4 b/test/core/http/response_corpus/d936dad71c129cf659097dc3db64550c4dd467f4
similarity index 100%
copy from test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4
copy to test/core/http/response_corpus/d936dad71c129cf659097dc3db64550c4dd467f4
diff --git a/test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b b/test/core/http/response_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
similarity index 100%
copy from test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
copy to test/core/http/response_corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b
diff --git a/test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089 b/test/core/http/response_corpus/e5c364b205855a2991ce07482aebb2a3a6147089
similarity index 100%
copy from test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089
copy to test/core/http/response_corpus/e5c364b205855a2991ce07482aebb2a3a6147089
diff --git a/test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb b/test/core/http/response_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
similarity index 100%
copy from test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
copy to test/core/http/response_corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb
diff --git a/test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066 b/test/core/http/response_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
similarity index 100%
copy from test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
copy to test/core/http/response_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066
diff --git a/test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b b/test/core/http/response_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
similarity index 100%
copy from test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
copy to test/core/http/response_corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b
Binary files differ
diff --git a/test/core/http/corpus/request1.txt b/test/core/http/response_corpus/request1.txt
similarity index 100%
copy from test/core/http/corpus/request1.txt
copy to test/core/http/response_corpus/request1.txt
diff --git a/test/core/http/corpus/request2.txt b/test/core/http/response_corpus/request2.txt
similarity index 100%
copy from test/core/http/corpus/request2.txt
copy to test/core/http/response_corpus/request2.txt
diff --git a/test/core/http/corpus/request3.txt b/test/core/http/response_corpus/request3.txt
similarity index 100%
copy from test/core/http/corpus/request3.txt
copy to test/core/http/response_corpus/request3.txt
diff --git a/test/core/http/corpus/request4.txt b/test/core/http/response_corpus/request4.txt
similarity index 100%
copy from test/core/http/corpus/request4.txt
copy to test/core/http/response_corpus/request4.txt
diff --git a/test/core/http/corpus/request5.txt b/test/core/http/response_corpus/request5.txt
similarity index 100%
copy from test/core/http/corpus/request5.txt
copy to test/core/http/response_corpus/request5.txt
diff --git a/test/core/http/corpus/response1.txt b/test/core/http/response_corpus/response1.txt
similarity index 100%
copy from test/core/http/corpus/response1.txt
copy to test/core/http/response_corpus/response1.txt
diff --git a/test/core/http/corpus/response2.txt b/test/core/http/response_corpus/response2.txt
similarity index 100%
copy from test/core/http/corpus/response2.txt
copy to test/core/http/response_corpus/response2.txt
diff --git a/test/core/http/corpus/response3.txt b/test/core/http/response_corpus/response3.txt
similarity index 100%
copy from test/core/http/corpus/response3.txt
copy to test/core/http/response_corpus/response3.txt
diff --git a/test/core/http/corpus/response4.txt b/test/core/http/response_corpus/response4.txt
similarity index 100%
copy from test/core/http/corpus/response4.txt
copy to test/core/http/response_corpus/response4.txt
diff --git a/test/core/http/corpus/response5.txt b/test/core/http/response_corpus/response5.txt
similarity index 100%
copy from test/core/http/corpus/response5.txt
copy to test/core/http/response_corpus/response5.txt
diff --git a/test/core/http/corpus/response6.txt b/test/core/http/response_corpus/response6.txt
similarity index 100%
copy from test/core/http/corpus/response6.txt
copy to test/core/http/response_corpus/response6.txt
diff --git a/test/core/http/corpus/toolong.txt b/test/core/http/response_corpus/toolong.txt
similarity index 100%
copy from test/core/http/corpus/toolong.txt
copy to test/core/http/response_corpus/toolong.txt
diff --git a/test/core/http/fuzzer.c b/test/core/http/response_fuzzer.c
similarity index 87%
rename from test/core/http/fuzzer.c
rename to test/core/http/response_fuzzer.c
index c3c634f..acde7c8 100644
--- a/test/core/http/fuzzer.c
+++ b/test/core/http/response_fuzzer.c
@@ -31,7 +31,6 @@
  *
  */
 
-#include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
 
@@ -44,11 +43,14 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   grpc_http_parser parser;
-  grpc_http_parser_init(&parser);
+  grpc_http_response response;
+  memset(&response, 0, sizeof(response));
+  grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
   gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
-  grpc_http_parser_parse(&parser, slice);
-  grpc_http_parser_eof(&parser);
+  GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice));
+  GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser));
   gpr_slice_unref(slice);
   grpc_http_parser_destroy(&parser);
+  grpc_http_response_destroy(&response);
   return 0;
 }
diff --git a/test/core/internal_api_canaries/iomgr.c b/test/core/internal_api_canaries/iomgr.c
index f87a80c..5e86c42 100644
--- a/test/core/internal_api_canaries/iomgr.c
+++ b/test/core/internal_api_canaries/iomgr.c
@@ -54,7 +54,7 @@
   grpc_closure closure;
   closure.cb = NULL;
   closure.cb_arg = NULL;
-  closure.final_data = 0;
+  closure.next_data.scratch = 0;
 
   grpc_closure_list closure_list = GRPC_CLOSURE_LIST_INIT;
   closure_list.head = NULL;
@@ -65,15 +65,14 @@
   grpc_closure_create(NULL, NULL);
 
   grpc_closure_list_move(NULL, NULL);
-  grpc_closure_list_add(NULL, NULL, true);
-  bool x = grpc_closure_list_empty(closure_list);
-  grpc_closure_next(&closure);
+  grpc_closure_list_append(NULL, NULL, GRPC_ERROR_CREATE("Foo"));
+  grpc_closure_list_empty(closure_list);
 
   /* exec_ctx.h */
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_exec_ctx_flush(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
-  grpc_exec_ctx_enqueue(&exec_ctx, &closure, x, NULL);
+  grpc_exec_ctx_sched(&exec_ctx, &closure, GRPC_ERROR_CREATE("Foo"), NULL);
   grpc_exec_ctx_enqueue_list(&exec_ctx, &closure_list, NULL);
 
   /* endpoint.h */
@@ -95,7 +94,7 @@
 
   /* executor.h */
   grpc_executor_init();
-  grpc_executor_enqueue(&closure, x);
+  grpc_executor_push(&closure, GRPC_ERROR_CREATE("Phi"));
   grpc_executor_shutdown();
 
   /* pollset.h */
@@ -104,9 +103,10 @@
   grpc_pollset_shutdown(NULL, NULL, NULL);
   grpc_pollset_reset(NULL);
   grpc_pollset_destroy(NULL);
-  grpc_pollset_work(NULL, NULL, NULL, gpr_now(GPR_CLOCK_REALTIME),
-                    gpr_now(GPR_CLOCK_MONOTONIC));
-  grpc_pollset_kick(NULL, NULL);
+  GRPC_ERROR_UNREF(grpc_pollset_work(NULL, NULL, NULL,
+                                     gpr_now(GPR_CLOCK_REALTIME),
+                                     gpr_now(GPR_CLOCK_MONOTONIC)));
+  GRPC_ERROR_UNREF(grpc_pollset_kick(NULL, NULL));
 }
 
 int main(void) {
diff --git a/test/core/internal_api_canaries/support.c b/test/core/internal_api_canaries/support.c
index c51cbf2..e992d2a 100644
--- a/test/core/internal_api_canaries/support.c
+++ b/test/core/internal_api_canaries/support.c
@@ -39,15 +39,15 @@
  * This test is NOT expected to be run directly.
  ******************************************************************************/
 
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/support/env.h"
-#include "src/core/lib/support/load_file.h"
 #include "src/core/lib/support/tmpfile.h"
 
 static void test_code(void) {
   /* env.h */
   gpr_set_env("abc", gpr_getenv("xyz"));
   /* load_file.h */
-  gpr_load_file("abc", 1, NULL);
+  grpc_load_file("abc", 1, NULL);
   /* tmpfile.h */
   fclose(gpr_tmpfile("foo", NULL));
 }
diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c
index 0df94a8..99b86b6 100644
--- a/test/core/iomgr/endpoint_pair_test.c
+++ b/test/core/iomgr/endpoint_pair_test.c
@@ -64,7 +64,8 @@
     {"tcp/tcp_socketpair", create_fixture_endpoint_pair, clean_up},
 };
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index 6d15ecf..b79c22e 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -33,6 +33,7 @@
 
 #include "test/core/iomgr/endpoint_tests.h"
 
+#include <stdbool.h>
 #include <sys/types.h>
 
 #include <grpc/support/alloc.h>
@@ -128,30 +129,30 @@
 };
 
 static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx,
-                                             void *data, bool success) {
+                                             void *data, grpc_error *error) {
   struct read_and_write_test_state *state = data;
 
   state->bytes_read += count_slices(
       state->incoming.slices, state->incoming.count, &state->current_read_data);
-  if (state->bytes_read == state->target_bytes || !success) {
+  if (state->bytes_read == state->target_bytes || error != GRPC_ERROR_NONE) {
     gpr_log(GPR_INFO, "Read handler done");
     gpr_mu_lock(g_mu);
-    state->read_done = 1 + success;
-    grpc_pollset_kick(g_pollset, NULL);
+    state->read_done = 1 + (error == GRPC_ERROR_NONE);
+    GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL));
     gpr_mu_unlock(g_mu);
-  } else if (success) {
+  } else if (error == GRPC_ERROR_NONE) {
     grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming,
                        &state->done_read);
   }
 }
 
 static void read_and_write_test_write_handler(grpc_exec_ctx *exec_ctx,
-                                              void *data, bool success) {
+                                              void *data, grpc_error *error) {
   struct read_and_write_test_state *state = data;
   gpr_slice *slices = NULL;
   size_t nslices;
 
-  if (success) {
+  if (error == GRPC_ERROR_NONE) {
     state->bytes_written += state->current_write_size;
     if (state->target_bytes - state->bytes_written <
         state->current_write_size) {
@@ -171,8 +172,8 @@
 
   gpr_log(GPR_INFO, "Write handler done");
   gpr_mu_lock(g_mu);
-  state->write_done = 1 + success;
-  grpc_pollset_kick(g_pollset, NULL);
+  state->write_done = 1 + (error == GRPC_ERROR_NONE);
+  GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL));
   gpr_mu_unlock(g_mu);
 }
 
@@ -182,7 +183,7 @@
  */
 static void read_and_write_test(grpc_endpoint_test_config config,
                                 size_t num_bytes, size_t write_size,
-                                size_t slice_size, int shutdown) {
+                                size_t slice_size, bool shutdown) {
   struct read_and_write_test_state state;
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
   grpc_endpoint_test_fixture f =
@@ -221,8 +222,8 @@
      for the first iteration as for later iterations. It does the right thing
      even when bytes_written is unsigned. */
   state.bytes_written -= state.current_write_size;
-  read_and_write_test_write_handler(&exec_ctx, &state, 1);
-  grpc_exec_ctx_finish(&exec_ctx);
+  read_and_write_test_write_handler(&exec_ctx, &state, GRPC_ERROR_NONE);
+  grpc_exec_ctx_flush(&exec_ctx);
 
   grpc_endpoint_read(&exec_ctx, state.read_ep, &state.incoming,
                      &state.done_read);
@@ -233,17 +234,19 @@
     gpr_log(GPR_DEBUG, "shutdown write");
     grpc_endpoint_shutdown(&exec_ctx, state.write_ep);
   }
-  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_exec_ctx_flush(&exec_ctx);
 
   gpr_mu_lock(g_mu);
   while (!state.read_done || !state.write_done) {
     grpc_pollset_worker *worker = NULL;
     GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) < 0);
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
   }
   gpr_mu_unlock(g_mu);
-  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_exec_ctx_flush(&exec_ctx);
 
   end_test(config);
   gpr_slice_buffer_destroy(&state.outgoing);
@@ -253,16 +256,73 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
+static void inc_on_failure(grpc_exec_ctx *exec_ctx, void *arg,
+                           grpc_error *error) {
+  *(int *)arg += (error != GRPC_ERROR_NONE);
+}
+
+static void wait_for_fail_count(grpc_exec_ctx *exec_ctx, int *fail_count,
+                                int want_fail_count) {
+  grpc_exec_ctx_flush(exec_ctx);
+  for (int i = 0; i < 5 && *fail_count < want_fail_count; i++) {
+    grpc_pollset_worker *worker = NULL;
+    gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
+    gpr_timespec deadline =
+        gpr_time_add(now, gpr_time_from_seconds(1, GPR_TIMESPAN));
+    gpr_mu_lock(g_mu);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(exec_ctx, g_pollset, &worker, now, deadline)));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_flush(exec_ctx);
+  }
+  GPR_ASSERT(*fail_count == want_fail_count);
+}
+
+static void multiple_shutdown_test(grpc_endpoint_test_config config) {
+  grpc_endpoint_test_fixture f =
+      begin_test(config, "multiple_shutdown_test", 128);
+  int fail_count = 0;
+
+  gpr_slice_buffer slice_buffer;
+  gpr_slice_buffer_init(&slice_buffer);
+
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset);
+  grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer,
+                     grpc_closure_create(inc_on_failure, &fail_count));
+  wait_for_fail_count(&exec_ctx, &fail_count, 0);
+  grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
+  wait_for_fail_count(&exec_ctx, &fail_count, 1);
+  grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer,
+                     grpc_closure_create(inc_on_failure, &fail_count));
+  wait_for_fail_count(&exec_ctx, &fail_count, 2);
+  gpr_slice_buffer_add(&slice_buffer, gpr_slice_from_copied_string("a"));
+  grpc_endpoint_write(&exec_ctx, f.client_ep, &slice_buffer,
+                      grpc_closure_create(inc_on_failure, &fail_count));
+  wait_for_fail_count(&exec_ctx, &fail_count, 3);
+  grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
+  wait_for_fail_count(&exec_ctx, &fail_count, 3);
+
+  gpr_slice_buffer_destroy(&slice_buffer);
+
+  grpc_endpoint_destroy(&exec_ctx, f.client_ep);
+  grpc_endpoint_destroy(&exec_ctx, f.server_ep);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
 void grpc_endpoint_tests(grpc_endpoint_test_config config,
                          grpc_pollset *pollset, gpr_mu *mu) {
   size_t i;
   g_pollset = pollset;
   g_mu = mu;
-  read_and_write_test(config, 10000000, 100000, 8192, 0);
-  read_and_write_test(config, 1000000, 100000, 1, 0);
-  read_and_write_test(config, 100000000, 100000, 1, 1);
+  multiple_shutdown_test(config);
+  read_and_write_test(config, 10000000, 100000, 8192, false);
+  read_and_write_test(config, 1000000, 100000, 1, false);
+  read_and_write_test(config, 100000000, 100000, 1, true);
   for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) {
-    read_and_write_test(config, 40320, i, i, 0);
+    read_and_write_test(config, 40320, i, i, false);
   }
   g_pollset = NULL;
+  g_mu = NULL;
 }
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index 24ba474..62dc24d 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -76,8 +76,8 @@
   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
   /* Reset the size of socket send buffer to the minimal value to facilitate
      buffer filling up and triggering notify_on_write  */
-  GPR_ASSERT(grpc_set_socket_sndbuf(fd, buffer_size_bytes));
-  GPR_ASSERT(grpc_set_socket_rcvbuf(fd, buffer_size_bytes));
+  GPR_ASSERT(grpc_set_socket_sndbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE);
+  GPR_ASSERT(grpc_set_socket_rcvbuf(fd, buffer_size_bytes) == GRPC_ERROR_NONE);
   /* Make fd non-blocking */
   flags = fcntl(fd, F_GETFL, 0);
   GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
@@ -132,14 +132,14 @@
 
 /* Called when data become readable in a session. */
 static void session_read_cb(grpc_exec_ctx *exec_ctx, void *arg, /*session */
-                            bool success) {
+                            grpc_error *error) {
   session *se = arg;
   int fd = grpc_fd_wrapped_fd(se->em_fd);
 
   ssize_t read_once = 0;
   ssize_t read_total = 0;
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     session_shutdown_cb(exec_ctx, arg, 1);
     return;
   }
@@ -184,13 +184,14 @@
 
   gpr_mu_lock(g_mu);
   sv->done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
 /* Called when a new TCP connection request arrives in the listening port. */
 static void listen_cb(grpc_exec_ctx *exec_ctx, void *arg, /*=sv_arg*/
-                      bool success) {
+                      grpc_error *error) {
   server *sv = arg;
   int fd;
   int flags;
@@ -199,7 +200,7 @@
   socklen_t slen = sizeof(ss);
   grpc_fd *listen_em_fd = sv->em_fd;
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     listen_shutdown_cb(exec_ctx, arg, 1);
     return;
   }
@@ -256,9 +257,11 @@
   while (!sv->done) {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          gpr_inf_future(GPR_CLOCK_MONOTONIC))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -299,17 +302,18 @@
   client *cl = arg;
   grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, "c");
   cl->done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
 }
 
 /* Write as much as possible, then register notify_on_write. */
 static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */
-                                 bool success) {
+                                 grpc_error *error) {
   client *cl = arg;
   int fd = grpc_fd_wrapped_fd(cl->em_fd);
   ssize_t write_once = 0;
 
-  if (!success) {
+  if (error != GRPC_ERROR_NONE) {
     gpr_mu_lock(g_mu);
     client_session_shutdown_cb(exec_ctx, arg, 1);
     gpr_mu_unlock(g_mu);
@@ -362,7 +366,7 @@
   cl->em_fd = grpc_fd_create(fd, "client");
   grpc_pollset_add_fd(exec_ctx, g_pollset, cl->em_fd);
 
-  client_session_write(exec_ctx, cl, 1);
+  client_session_write(exec_ctx, cl, GRPC_ERROR_NONE);
 }
 
 /* Wait for the signal to shutdown a client. */
@@ -371,9 +375,11 @@
   while (!cl->done) {
     grpc_pollset_worker *worker = NULL;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          gpr_inf_future(GPR_CLOCK_MONOTONIC))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -410,22 +416,26 @@
 void destroy_change_data(fd_change_data *fdc) {}
 
 static void first_read_callback(grpc_exec_ctx *exec_ctx,
-                                void *arg /* fd_change_data */, bool success) {
+                                void *arg /* fd_change_data */,
+                                grpc_error *error) {
   fd_change_data *fdc = arg;
 
   gpr_mu_lock(g_mu);
   fdc->cb_that_ran = first_read_callback;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
 static void second_read_callback(grpc_exec_ctx *exec_ctx,
-                                 void *arg /* fd_change_data */, bool success) {
+                                 void *arg /* fd_change_data */,
+                                 grpc_error *error) {
   fd_change_data *fdc = arg;
 
   gpr_mu_lock(g_mu);
   fdc->cb_that_ran = second_read_callback;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
@@ -471,9 +481,11 @@
   gpr_mu_lock(g_mu);
   while (a.cb_that_ran == NULL) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          gpr_inf_future(GPR_CLOCK_MONOTONIC))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -495,9 +507,11 @@
   gpr_mu_lock(g_mu);
   while (b.cb_that_ran == NULL) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          gpr_inf_future(GPR_CLOCK_MONOTONIC))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -513,7 +527,8 @@
   close(sv[1]);
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/support/load_file_test.c b/test/core/iomgr/load_file_test.c
similarity index 86%
rename from test/core/support/load_file_test.c
rename to test/core/iomgr/load_file_test.c
index 0125fd9..f70295a 100644
--- a/test/core/support/load_file_test.c
+++ b/test/core/iomgr/load_file_test.c
@@ -38,7 +38,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
 #include "test/core/util/test_config.h"
@@ -51,7 +51,7 @@
   FILE *tmp = NULL;
   gpr_slice slice;
   gpr_slice slice_with_null_term;
-  int success;
+  grpc_error *error;
   char *tmp_name;
 
   LOG_TEST_NAME("test_load_empty_file");
@@ -61,12 +61,12 @@
   GPR_ASSERT(tmp != NULL);
   fclose(tmp);
 
-  slice = gpr_load_file(tmp_name, 0, &success);
-  GPR_ASSERT(success == 1);
+  error = grpc_load_file(tmp_name, 0, &slice);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice) == 0);
 
-  slice_with_null_term = gpr_load_file(tmp_name, 1, &success);
-  GPR_ASSERT(success == 1);
+  error = grpc_load_file(tmp_name, 1, &slice_with_null_term);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice_with_null_term) == 1);
   GPR_ASSERT(GPR_SLICE_START_PTR(slice_with_null_term)[0] == 0);
 
@@ -79,7 +79,7 @@
 static void test_load_failure(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
-  int success;
+  grpc_error *error;
   char *tmp_name;
 
   LOG_TEST_NAME("test_load_failure");
@@ -90,8 +90,9 @@
   fclose(tmp);
   remove(tmp_name);
 
-  slice = gpr_load_file(tmp_name, 0, &success);
-  GPR_ASSERT(success == 0);
+  error = grpc_load_file(tmp_name, 0, &slice);
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
+  GRPC_ERROR_UNREF(error);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice) == 0);
   gpr_free(tmp_name);
   gpr_slice_unref(slice);
@@ -101,7 +102,7 @@
   FILE *tmp = NULL;
   gpr_slice slice;
   gpr_slice slice_with_null_term;
-  int success;
+  grpc_error *error;
   char *tmp_name;
   const char *blah = "blah";
 
@@ -113,13 +114,13 @@
   GPR_ASSERT(fwrite(blah, 1, strlen(blah), tmp) == strlen(blah));
   fclose(tmp);
 
-  slice = gpr_load_file(tmp_name, 0, &success);
-  GPR_ASSERT(success == 1);
+  error = grpc_load_file(tmp_name, 0, &slice);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice) == strlen(blah));
   GPR_ASSERT(!memcmp(GPR_SLICE_START_PTR(slice), blah, strlen(blah)));
 
-  slice_with_null_term = gpr_load_file(tmp_name, 1, &success);
-  GPR_ASSERT(success == 1);
+  error = grpc_load_file(tmp_name, 1, &slice_with_null_term);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice_with_null_term) == (strlen(blah) + 1));
   GPR_ASSERT(strcmp((const char *)GPR_SLICE_START_PTR(slice_with_null_term),
                     blah) == 0);
@@ -133,7 +134,7 @@
 static void test_load_big_file(void) {
   FILE *tmp = NULL;
   gpr_slice slice;
-  int success;
+  grpc_error *error;
   char *tmp_name;
   static const size_t buffer_size = 124631;
   unsigned char *buffer = gpr_malloc(buffer_size);
@@ -150,8 +151,8 @@
   GPR_ASSERT(fwrite(buffer, 1, buffer_size, tmp) == buffer_size);
   fclose(tmp);
 
-  slice = gpr_load_file(tmp_name, 0, &success);
-  GPR_ASSERT(success == 1);
+  error = grpc_load_file(tmp_name, 0, &slice);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(GPR_SLICE_LENGTH(slice) == buffer_size);
   current = GPR_SLICE_START_PTR(slice);
   for (i = 0; i < buffer_size; i++) {
diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c
index c3ede18..4417d96 100644
--- a/test/core/iomgr/resolve_address_test.c
+++ b/test/core/iomgr/resolve_address_test.c
@@ -42,54 +42,74 @@
   return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100);
 }
 
-static void must_succeed(grpc_exec_ctx *exec_ctx, void *evp,
-                         grpc_resolved_addresses *p) {
-  GPR_ASSERT(p);
-  GPR_ASSERT(p->naddrs >= 1);
-  grpc_resolved_addresses_destroy(p);
-  gpr_event_set(evp, (void *)1);
+typedef struct args_struct {
+  gpr_event ev;
+  grpc_resolved_addresses *addrs;
+} args_struct;
+
+void args_init(args_struct *args) {
+  gpr_event_init(&args->ev);
+  args->addrs = NULL;
 }
 
-static void must_fail(grpc_exec_ctx *exec_ctx, void *evp,
-                      grpc_resolved_addresses *p) {
-  GPR_ASSERT(!p);
-  gpr_event_set(evp, (void *)1);
+void args_finish(args_struct *args) {
+  GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline()));
+  grpc_resolved_addresses_destroy(args->addrs);
+}
+
+static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp,
+                         grpc_error *err) {
+  args_struct *args = argsp;
+  GPR_ASSERT(err == GRPC_ERROR_NONE);
+  GPR_ASSERT(args->addrs != NULL);
+  GPR_ASSERT(args->addrs->naddrs > 0);
+  gpr_event_set(&args->ev, (void *)1);
+}
+
+static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) {
+  args_struct *args = argsp;
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
+  gpr_event_set(&args->ev, (void *)1);
 }
 
 static void test_localhost(void) {
-  gpr_event ev;
-  gpr_event_init(&ev);
+  args_struct args;
+  args_init(&args);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_resolve_address(&exec_ctx, "localhost:1", NULL, must_succeed, &ev);
+  grpc_resolve_address(&exec_ctx, "localhost:1", NULL,
+                       grpc_closure_create(must_succeed, &args), &args.addrs);
   grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+  args_finish(&args);
 }
 
 static void test_default_port(void) {
-  gpr_event ev;
-  gpr_event_init(&ev);
+  args_struct args;
+  args_init(&args);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_resolve_address(&exec_ctx, "localhost", "1", must_succeed, &ev);
+  grpc_resolve_address(&exec_ctx, "localhost", "1",
+                       grpc_closure_create(must_succeed, &args), &args.addrs);
   grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+  args_finish(&args);
 }
 
 static void test_missing_default_port(void) {
-  gpr_event ev;
-  gpr_event_init(&ev);
+  args_struct args;
+  args_init(&args);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_resolve_address(&exec_ctx, "localhost", NULL, must_fail, &ev);
+  grpc_resolve_address(&exec_ctx, "localhost", NULL,
+                       grpc_closure_create(must_fail, &args), &args.addrs);
   grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+  args_finish(&args);
 }
 
 static void test_ipv6_with_port(void) {
-  gpr_event ev;
-  gpr_event_init(&ev);
+  args_struct args;
+  args_init(&args);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_resolve_address(&exec_ctx, "[2001:db8::1]:1", NULL, must_succeed, &ev);
+  grpc_resolve_address(&exec_ctx, "[2001:db8::1]:1", NULL,
+                       grpc_closure_create(must_succeed, &args), &args.addrs);
   grpc_exec_ctx_finish(&exec_ctx);
-  GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+  args_finish(&args);
 }
 
 static void test_ipv6_without_port(void) {
@@ -98,12 +118,13 @@
   };
   unsigned i;
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
-    gpr_event ev;
-    gpr_event_init(&ev);
+    args_struct args;
+    args_init(&args);
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_resolve_address(&exec_ctx, kCases[i], "80", must_succeed, &ev);
+    grpc_resolve_address(&exec_ctx, kCases[i], "80",
+                         grpc_closure_create(must_succeed, &args), &args.addrs);
     grpc_exec_ctx_finish(&exec_ctx);
-    GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+    args_finish(&args);
   }
 }
 
@@ -113,12 +134,13 @@
   };
   unsigned i;
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
-    gpr_event ev;
-    gpr_event_init(&ev);
+    args_struct args;
+    args_init(&args);
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_resolve_address(&exec_ctx, kCases[i], NULL, must_fail, &ev);
+    grpc_resolve_address(&exec_ctx, kCases[i], NULL,
+                         grpc_closure_create(must_fail, &args), &args.addrs);
     grpc_exec_ctx_finish(&exec_ctx);
-    GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+    args_finish(&args);
   }
 }
 
@@ -128,12 +150,13 @@
   };
   unsigned i;
   for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) {
-    gpr_event ev;
-    gpr_event_init(&ev);
+    args_struct args;
+    args_init(&args);
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_resolve_address(&exec_ctx, kCases[i], "1", must_fail, &ev);
+    grpc_resolve_address(&exec_ctx, kCases[i], "1",
+                         grpc_closure_create(must_fail, &args), &args.addrs);
     grpc_exec_ctx_finish(&exec_ctx);
-    GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
+    args_finish(&args);
   }
 }
 
diff --git a/test/core/iomgr/socket_utils_test.c b/test/core/iomgr/socket_utils_test.c
index 85c027a..297531c 100644
--- a/test/core/iomgr/socket_utils_test.c
+++ b/test/core/iomgr/socket_utils_test.c
@@ -47,14 +47,22 @@
   sock = socket(PF_INET, SOCK_STREAM, 0);
   GPR_ASSERT(sock > 0);
 
-  GPR_ASSERT(grpc_set_socket_nonblocking(sock, 1));
-  GPR_ASSERT(grpc_set_socket_nonblocking(sock, 0));
-  GPR_ASSERT(grpc_set_socket_cloexec(sock, 1));
-  GPR_ASSERT(grpc_set_socket_cloexec(sock, 0));
-  GPR_ASSERT(grpc_set_socket_reuse_addr(sock, 1));
-  GPR_ASSERT(grpc_set_socket_reuse_addr(sock, 0));
-  GPR_ASSERT(grpc_set_socket_low_latency(sock, 1));
-  GPR_ASSERT(grpc_set_socket_low_latency(sock, 0));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
+                               grpc_set_socket_nonblocking(sock, 1)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
+                               grpc_set_socket_nonblocking(sock, 0)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
+                               grpc_set_socket_cloexec(sock, 1)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
+                               grpc_set_socket_cloexec(sock, 0)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
+                               grpc_set_socket_reuse_addr(sock, 1)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
+                               grpc_set_socket_reuse_addr(sock, 0)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
+                               grpc_set_socket_low_latency(sock, 1)));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
+                               grpc_set_socket_low_latency(sock, 0)));
 
   close(sock);
 
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index 22dc936..d0c1047 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -63,22 +63,24 @@
 static void finish_connection() {
   gpr_mu_lock(g_mu);
   g_connections_complete++;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
-static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
   GPR_ASSERT(g_connecting != NULL);
-  GPR_ASSERT(success);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   grpc_endpoint_shutdown(exec_ctx, g_connecting);
   grpc_endpoint_destroy(exec_ctx, g_connecting);
   g_connecting = NULL;
   finish_connection();
 }
 
-static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   GPR_ASSERT(g_connecting == NULL);
-  GPR_ASSERT(!success);
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
   finish_connection();
 }
 
@@ -125,9 +127,11 @@
 
   while (g_connections_complete == connections_complete_before) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_flush(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -168,7 +172,9 @@
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec polling_deadline = test_deadline();
     if (!grpc_timer_check(&exec_ctx, now, &polling_deadline)) {
-      grpc_pollset_work(&exec_ctx, g_pollset, &worker, now, polling_deadline);
+      GPR_ASSERT(GRPC_LOG_IF_ERROR(
+          "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, now,
+                                            polling_deadline)));
     }
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_flush(&exec_ctx);
@@ -179,7 +185,8 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index 19ba258..4261456 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -139,12 +139,13 @@
   return num_bytes;
 }
 
-static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data,
+                    grpc_error *error) {
   struct read_socket_state *state = (struct read_socket_state *)user_data;
   size_t read_bytes;
   int current_data;
 
-  GPR_ASSERT(success);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
 
   gpr_mu_lock(g_mu);
   current_data = state->read_bytes % 256;
@@ -192,8 +193,10 @@
   gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -238,8 +241,10 @@
   gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -281,13 +286,15 @@
 }
 
 static void write_done(grpc_exec_ctx *exec_ctx,
-                       void *user_data /* write_socket_state */, bool success) {
+                       void *user_data /* write_socket_state */,
+                       grpc_error *error) {
   struct write_socket_state *state = (struct write_socket_state *)user_data;
   gpr_log(GPR_INFO, "Write done callback called");
   gpr_mu_lock(g_mu);
   gpr_log(GPR_INFO, "Signalling write done");
   state->write_done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
@@ -306,9 +313,11 @@
   for (;;) {
     grpc_pollset_worker *worker = NULL;
     gpr_mu_lock(g_mu);
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC),
+                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     do {
@@ -371,8 +380,10 @@
     if (state.write_done) {
       break;
     }
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -385,10 +396,11 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *errors) {
   int *done = arg;
   *done = 1;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
 }
 
 /* Do a read_test, then release fd and try to read/write again. Verify that
@@ -429,8 +441,10 @@
   gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -443,8 +457,10 @@
   gpr_mu_lock(g_mu);
   while (!fd_released_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
   }
   gpr_mu_unlock(g_mu);
   GPR_ASSERT(fd_released_done == 1);
@@ -506,7 +522,8 @@
     {"tcp/tcp_socketpair", create_fixture_tcp_socketpair, clean_up},
 };
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
@@ -517,8 +534,8 @@
   grpc_init();
   g_pollset = gpr_malloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
-  run_tests();
   grpc_endpoint_tests(configs[0], g_pollset, g_mu);
+  run_tests();
   grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
   grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 222ae77..eda774f 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -90,7 +90,7 @@
 }
 
 static void server_weak_ref_shutdown(grpc_exec_ctx *exec_ctx, void *arg,
-                                     bool success) {
+                                     grpc_error *error) {
   server_weak_ref *weak_ref = arg;
   weak_ref->server = NULL;
 }
@@ -121,20 +121,23 @@
   gpr_mu_lock(g_mu);
   on_connect_result_set(&g_result, acceptor);
   g_nconnects++;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
 static void test_no_op(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, &s));
   grpc_tcp_server_unref(&exec_ctx, s);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_no_op_with_start(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, &s));
   LOG_TEST("test_no_op_with_start");
   grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL);
   grpc_tcp_server_unref(&exec_ctx, s);
@@ -144,13 +147,16 @@
 static void test_no_op_with_port(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   struct sockaddr_in addr;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, &s));
   LOG_TEST("test_no_op_with_port");
 
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
-  GPR_ASSERT(
-      grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr)) > 0);
+  int port;
+  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr),
+                                      &port) == GRPC_ERROR_NONE &&
+             port > 0);
 
   grpc_tcp_server_unref(&exec_ctx, s);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -159,13 +165,16 @@
 static void test_no_op_with_port_and_start(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   struct sockaddr_in addr;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, &s));
   LOG_TEST("test_no_op_with_port_and_start");
+  int port;
 
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
-  GPR_ASSERT(
-      grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr)) > 0);
+  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr),
+                                      &port) == GRPC_ERROR_NONE &&
+             port > 0);
 
   grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL);
 
@@ -189,8 +198,10 @@
   while (g_nconnects == nconnects_before &&
          gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(exec_ctx, g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(exec_ctx, g_pollset, &worker,
+                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(exec_ctx);
     gpr_mu_lock(g_mu);
@@ -214,7 +225,8 @@
   int svr_port;
   unsigned svr1_fd_count;
   int svr1_port;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, &s));
   unsigned i;
   server_weak_ref weak_ref;
   server_weak_ref_init(&weak_ref);
@@ -223,14 +235,17 @@
   memset(&addr, 0, sizeof(addr));
   memset(&addr1, 0, sizeof(addr1));
   addr.ss_family = addr1.ss_family = AF_INET;
-  svr_port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len);
+  GPR_ASSERT(GRPC_ERROR_NONE ==
+             grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len,
+                                      &svr_port));
   GPR_ASSERT(svr_port > 0);
   /* Cannot use wildcard (port==0), because add_port() will try to reuse the
      same port as a previous add_port(). */
   svr1_port = grpc_pick_unused_port_or_die();
   grpc_sockaddr_set_port((struct sockaddr *)&addr1, svr1_port);
-  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr1, addr_len) ==
-             svr1_port);
+  GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr1, addr_len,
+                                      &svr_port) == GRPC_ERROR_NONE &&
+             svr_port == svr1_port);
 
   /* Bad port_index. */
   GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0);
@@ -306,7 +321,8 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c
index 2e0f5c8..be8988a 100644
--- a/test/core/iomgr/timer_list_test.c
+++ b/test/core/iomgr/timer_list_test.c
@@ -42,8 +42,8 @@
 
 static int cb_called[MAX_CB][2];
 
-static void cb(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  cb_called[(intptr_t)arg][success]++;
+static void cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+  cb_called[(intptr_t)arg][error == GRPC_ERROR_NONE]++;
 }
 
 static void add_test(void) {
diff --git a/test/core/iomgr/workqueue_test.c b/test/core/iomgr/workqueue_test.c
index 953cc35..76ecfae 100644
--- a/test/core/iomgr/workqueue_test.c
+++ b/test/core/iomgr/workqueue_test.c
@@ -42,17 +42,20 @@
 static gpr_mu *g_mu;
 static grpc_pollset *g_pollset;
 
-static void must_succeed(grpc_exec_ctx *exec_ctx, void *p, bool success) {
-  GPR_ASSERT(success == 1);
+static void must_succeed(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   gpr_mu_lock(g_mu);
   *(int *)p = 1;
-  grpc_pollset_kick(g_pollset, NULL);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
   gpr_mu_unlock(g_mu);
 }
 
 static void test_ref_unref(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx);
+  grpc_workqueue *wq;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_workqueue_create",
+                               grpc_workqueue_create(&exec_ctx, &wq)));
   GRPC_WORKQUEUE_REF(wq, "test");
   GRPC_WORKQUEUE_UNREF(&exec_ctx, wq, "test");
   GRPC_WORKQUEUE_UNREF(&exec_ctx, wq, "destroy");
@@ -63,19 +66,23 @@
   grpc_closure c;
   int done = 0;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx);
+  grpc_workqueue *wq;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_workqueue_create",
+                               grpc_workqueue_create(&exec_ctx, &wq)));
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
   grpc_pollset_worker *worker = NULL;
   grpc_closure_init(&c, must_succeed, &done);
 
-  grpc_workqueue_push(wq, &c, 1);
+  grpc_workqueue_enqueue(&exec_ctx, wq, &c, GRPC_ERROR_NONE);
   grpc_workqueue_add_to_pollset(&exec_ctx, wq, g_pollset);
 
   gpr_mu_lock(g_mu);
   GPR_ASSERT(!done);
   while (!done) {
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(deadline.clock_type), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(deadline.clock_type), deadline)));
   }
   gpr_mu_unlock(g_mu);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -89,19 +96,24 @@
   grpc_closure c;
   int done = 0;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx);
+  grpc_workqueue *wq;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_workqueue_create",
+                               grpc_workqueue_create(&exec_ctx, &wq)));
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
   grpc_pollset_worker *worker = NULL;
   grpc_closure_init(&c, must_succeed, &done);
 
-  grpc_exec_ctx_enqueue(&exec_ctx, &c, true, NULL);
+  grpc_exec_ctx_sched(&exec_ctx, &c, GRPC_ERROR_NONE, NULL);
   grpc_workqueue_flush(&exec_ctx, wq);
   grpc_workqueue_add_to_pollset(&exec_ctx, wq, g_pollset);
 
   gpr_mu_lock(g_mu);
+  GPR_ASSERT(!done);
   while (!done) {
-    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
-                      gpr_now(deadline.clock_type), deadline);
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, g_pollset, &worker,
+                          gpr_now(deadline.clock_type), deadline)));
   }
   gpr_mu_unlock(g_mu);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -111,7 +123,8 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c
index 3c36b76..1bd135f 100644
--- a/test/core/security/create_jwt.c
+++ b/test/core/security/create_jwt.c
@@ -34,8 +34,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
-#include "src/core/lib/support/load_file.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/cmdline.h>
@@ -45,13 +45,10 @@
 void create_jwt(const char *json_key_file_path, const char *service_url,
                 const char *scope) {
   grpc_auth_json_key key;
-  int ok = 0;
   char *jwt;
-  gpr_slice json_key_data = gpr_load_file(json_key_file_path, 1, &ok);
-  if (!ok) {
-    fprintf(stderr, "Could not read %s.\n", json_key_file_path);
-    exit(1);
-  }
+  gpr_slice json_key_data;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "load_file", grpc_load_file(json_key_file_path, 1, &json_key_data)));
   key = grpc_auth_json_key_create_from_string(
       (const char *)GPR_SLICE_START_PTR(json_key_data));
   gpr_slice_unref(json_key_data);
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 31e0637..e703dbd 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -157,7 +157,7 @@
   grpc_httpcli_response response;
   memset(&response, 0, sizeof(grpc_httpcli_response));
   response.status = status;
-  response.body = (char *)body;
+  response.body = gpr_strdup((char *)body);
   response.body_length = strlen(body);
   return response;
 }
@@ -247,6 +247,7 @@
                                "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
              0);
   grpc_credentials_md_store_unref(token_md);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_bad_http_status(void) {
@@ -257,6 +258,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_empty_http_body(void) {
@@ -266,6 +268,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_invalid_json(void) {
@@ -279,6 +282,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_missing_token(void) {
@@ -291,6 +295,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_missing_token_type(void) {
@@ -304,6 +309,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(
@@ -317,6 +323,7 @@
   GPR_ASSERT(grpc_oauth2_token_fetcher_credentials_parse_server_response(
                  &response, &token_md, &token_lifetime) ==
              GRPC_CREDENTIALS_ERROR);
+  grpc_http_response_destroy(&response);
 }
 
 static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems,
@@ -549,37 +556,37 @@
 
 static int compute_engine_httpcli_get_success_override(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
-  grpc_httpcli_response response =
-      http_response(200, valid_oauth2_json_response);
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
   validate_compute_engine_http_request(request);
-  on_response(exec_ctx, user_data, &response);
+  *response = http_response(200, valid_oauth2_json_response);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
 static int compute_engine_httpcli_get_failure_override(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
-  grpc_httpcli_response response = http_response(403, "Not Authorized.");
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
   validate_compute_engine_http_request(request);
-  on_response(exec_ctx, user_data, &response);
+  *response = http_response(403, "Not Authorized.");
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
 static int httpcli_post_should_not_be_called(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
     const char *body_bytes, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data) {
+    grpc_closure *on_done, grpc_httpcli_response *response) {
   GPR_ASSERT("HTTP POST should not be called" == NULL);
   return 1;
 }
 
-static int httpcli_get_should_not_be_called(
-    grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
+static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx,
+                                            const grpc_httpcli_request *request,
+                                            gpr_timespec deadline,
+                                            grpc_closure *on_done,
+                                            grpc_httpcli_response *response) {
   GPR_ASSERT("HTTP GET should not be called" == NULL);
   return 1;
 }
@@ -653,21 +660,20 @@
 static int refresh_token_httpcli_post_success(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
     const char *body, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data) {
-  grpc_httpcli_response response =
-      http_response(200, valid_oauth2_json_response);
+    grpc_closure *on_done, grpc_httpcli_response *response) {
   validate_refresh_token_http_request(request, body, body_size);
-  on_response(exec_ctx, user_data, &response);
+  *response = http_response(200, valid_oauth2_json_response);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
 static int refresh_token_httpcli_post_failure(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
     const char *body, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data) {
-  grpc_httpcli_response response = http_response(403, "Not Authorized.");
+    grpc_closure *on_done, grpc_httpcli_response *response) {
   validate_refresh_token_http_request(request, body, body_size);
-  on_response(exec_ctx, user_data, &response);
+  *response = http_response(403, "Not Authorized.");
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -899,17 +905,17 @@
 
 static int default_creds_gce_detection_httpcli_get_success_override(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
-  grpc_httpcli_response response = http_response(200, "");
-  grpc_http_header header;
-  header.key = "Metadata-Flavor";
-  header.value = "Google";
-  response.hdr_count = 1;
-  response.hdrs = &header;
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
+  *response = http_response(200, "");
+  grpc_http_header *headers = gpr_malloc(sizeof(*headers) * 1);
+  headers[0].key = gpr_strdup("Metadata-Flavor");
+  headers[0].value = gpr_strdup("Google");
+  response->hdr_count = 1;
+  response->hdrs = headers;
   GPR_ASSERT(strcmp(request->http.path, "/") == 0);
   GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0);
-  on_response(exec_ctx, user_data, &response);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -961,13 +967,13 @@
 
 static int default_creds_gce_detection_httpcli_get_failure_override(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
   /* No magic header. */
-  grpc_httpcli_response response = http_response(200, "");
   GPR_ASSERT(strcmp(request->http.path, "/") == 0);
   GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0);
-  on_response(exec_ctx, user_data, &response);
+  *response = http_response(200, "");
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index 2a102fb..292f59a 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -42,19 +42,16 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/credentials/credentials.h"
-#include "src/core/lib/support/load_file.h"
 #include "test/core/security/oauth2_utils.h"
 
 static grpc_call_credentials *create_refresh_token_creds(
     const char *json_refresh_token_file_path) {
-  int success;
-  gpr_slice refresh_token =
-      gpr_load_file(json_refresh_token_file_path, 1, &success);
-  if (!success) {
-    gpr_log(GPR_ERROR, "Could not read file %s.", json_refresh_token_file_path);
-    exit(1);
-  }
+  gpr_slice refresh_token;
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "load_file",
+      grpc_load_file(json_refresh_token_file_path, 1, &refresh_token)));
   return grpc_google_refresh_token_credentials_create(
       (const char *)GPR_SLICE_START_PTR(refresh_token), NULL);
 }
diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c
index 7f4f4ff..36b331a 100644
--- a/test/core/security/jwt_verifier_test.c
+++ b/test/core/security/jwt_verifier_test.c
@@ -278,24 +278,23 @@
 static int httpcli_post_should_not_be_called(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
     const char *body_bytes, size_t body_size, gpr_timespec deadline,
-    grpc_httpcli_response_cb on_response, void *user_data) {
+    grpc_closure *on_done, grpc_httpcli_response *response) {
   GPR_ASSERT("HTTP POST should not be called" == NULL);
   return 1;
 }
 
 static int httpcli_get_google_keys_for_email(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
-  grpc_httpcli_response response = http_response(200, good_google_email_keys());
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
+  *response = http_response(200, good_google_email_keys());
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
   GPR_ASSERT(strcmp(request->http.path,
                     "/robot/v1/metadata/x509/"
                     "777-abaslkan11hlb6nmim3bpspl31ud@developer."
                     "gserviceaccount.com") == 0);
-  on_response(exec_ctx, user_data, &response);
-  gpr_free(response.body);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -325,22 +324,21 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static int httpcli_get_custom_keys_for_email(
     grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
-  grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
+    gpr_timespec deadline, grpc_closure *on_done,
+    grpc_httpcli_response *response) {
+  *response = http_response(200, gpr_strdup(good_jwk_set));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
   GPR_ASSERT(strcmp(request->http.path, "/jwk/foo@bar.com") == 0);
-  on_response(exec_ctx, user_data, &response);
-  gpr_free(response.body);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -360,40 +358,36 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static int httpcli_get_jwk_set(grpc_exec_ctx *exec_ctx,
                                const grpc_httpcli_request *request,
-                               gpr_timespec deadline,
-                               grpc_httpcli_response_cb on_response,
-                               void *user_data) {
-  grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
+                               gpr_timespec deadline, grpc_closure *on_done,
+                               grpc_httpcli_response *response) {
+  *response = http_response(200, gpr_strdup(good_jwk_set));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
   GPR_ASSERT(strcmp(request->http.path, "/oauth2/v3/certs") == 0);
-  on_response(exec_ctx, user_data, &response);
-  gpr_free(response.body);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
 static int httpcli_get_openid_config(grpc_exec_ctx *exec_ctx,
                                      const grpc_httpcli_request *request,
                                      gpr_timespec deadline,
-                                     grpc_httpcli_response_cb on_response,
-                                     void *user_data) {
-  grpc_httpcli_response response =
-      http_response(200, gpr_strdup(good_openid_config));
+                                     grpc_closure *on_done,
+                                     grpc_httpcli_response *response) {
+  *response = http_response(200, gpr_strdup(good_openid_config));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
   GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0);
   GPR_ASSERT(strcmp(request->http.path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
   grpc_httpcli_set_override(httpcli_get_jwk_set,
                             httpcli_post_should_not_be_called);
-  on_response(exec_ctx, user_data, &response);
-  gpr_free(response.body);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -413,10 +407,10 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void on_verification_key_retrieval_error(void *user_data,
@@ -429,14 +423,11 @@
 
 static int httpcli_get_bad_json(grpc_exec_ctx *exec_ctx,
                                 const grpc_httpcli_request *request,
-                                gpr_timespec deadline,
-                                grpc_httpcli_response_cb on_response,
-                                void *user_data) {
-  grpc_httpcli_response response =
-      http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
+                                gpr_timespec deadline, grpc_closure *on_done,
+                                grpc_httpcli_response *response) {
+  *response = http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
-  on_response(exec_ctx, user_data, &response);
-  gpr_free(response.body);
+  grpc_exec_ctx_sched(exec_ctx, on_done, GRPC_ERROR_NONE, NULL);
   return 1;
 }
 
@@ -457,10 +448,10 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_key_retrieval_error,
                            (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_jwt_verifier_bad_json_key(void) {
@@ -480,10 +471,10 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_key_retrieval_error,
                            (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void corrupt_jwt_sig(char *jwt) {
@@ -529,16 +520,17 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_bad_signature,
                            (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static int httpcli_get_should_not_be_called(
-    grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
-    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
-    void *user_data) {
+static int httpcli_get_should_not_be_called(grpc_exec_ctx *exec_ctx,
+                                            const grpc_httpcli_request *request,
+                                            gpr_timespec deadline,
+                                            grpc_closure *on_done,
+                                            grpc_httpcli_response *response) {
   GPR_ASSERT(0);
   return 1;
 }
@@ -559,9 +551,9 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, "bad jwt",
                            expected_audience, on_verification_bad_format,
                            (void *)expected_user_data);
+  grpc_exec_ctx_finish(&exec_ctx);
   grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 /* find verification key: bad jks, cannot find key in jks */
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index cb27a1a..a334edc 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -70,11 +70,14 @@
   gpr_mu_lock(request->mu);
   request->is_done = 1;
   request->token = token;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&request->pops), NULL);
+  GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&request->pops), NULL));
   gpr_mu_unlock(request->mu);
 }
 
-static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused, bool success) {}
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused,
+                       grpc_error *error) {}
 
 char *grpc_test_fetch_oauth2_token_with_credentials(
     grpc_call_credentials *creds) {
@@ -98,9 +101,14 @@
   gpr_mu_lock(request.mu);
   while (!request.is_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&request.pops),
-                      &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx,
+                              grpc_polling_entity_pollset(&request.pops),
+                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                              gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
+      request.is_done = 1;
+    }
   }
   gpr_mu_unlock(request.mu);
 
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 07c8c58..18fbc3c 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -67,7 +67,9 @@
   }
   gpr_mu_lock(sync->mu);
   sync->is_done = 1;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&sync->pops), NULL);
+  GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&sync->pops), NULL));
   gpr_mu_unlock(sync->mu);
 }
 
@@ -106,9 +108,13 @@
   gpr_mu_lock(sync.mu);
   while (!sync.is_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&sync.pops),
-                      &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx,
+                              grpc_polling_entity_pollset(&sync.pops), &worker,
+                              gpr_now(GPR_CLOCK_MONOTONIC),
+                              gpr_inf_future(GPR_CLOCK_MONOTONIC))))
+      sync.is_done = 1;
     gpr_mu_unlock(sync.mu);
     grpc_exec_ctx_flush(&exec_ctx);
     gpr_mu_lock(sync.mu);
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index 6aba21a..1d2bf73 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -139,7 +139,8 @@
      secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up},
 };
 
-static void inc_call_ctr(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void inc_call_ctr(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
   ++*(int *)arg;
 }
 
@@ -172,7 +173,8 @@
   clean_up();
 }
 
-static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
   grpc_pollset_destroy(p);
 }
 
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
index ecb873b..728d2d6 100644
--- a/test/core/security/verify_jwt.c
+++ b/test/core/security/verify_jwt.c
@@ -81,7 +81,7 @@
 
   gpr_mu_lock(sync->mu);
   sync->is_done = 1;
-  grpc_pollset_kick(sync->pollset, NULL);
+  GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(sync->pollset, NULL));
   gpr_mu_unlock(sync->mu);
 }
 
@@ -115,9 +115,12 @@
   gpr_mu_lock(sync.mu);
   while (!sync.is_done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, sync.pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx, sync.pollset, &worker,
+                              gpr_now(GPR_CLOCK_MONOTONIC),
+                              gpr_inf_future(GPR_CLOCK_MONOTONIC))))
+      sync.is_done = true;
     gpr_mu_unlock(sync.mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(sync.mu);
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index 2fcd7f5..1486d25 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -96,8 +96,8 @@
   cc = grpc_completion_queue_create(NULL);
 
   grpc_cq_begin_op(cc, tag);
-  grpc_cq_end_op(&exec_ctx, cc, tag, 1, do_nothing_end_completion, NULL,
-                 &completion);
+  grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE, do_nothing_end_completion,
+                 NULL, &completion);
 
   ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
@@ -155,8 +155,8 @@
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
     grpc_cq_begin_op(cc, tags[i]);
-    grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
-                   &completions[i]);
+    grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
+                   do_nothing_end_completion, NULL, &completions[i]);
   }
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -167,8 +167,8 @@
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
     grpc_cq_begin_op(cc, tags[i]);
-    grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
-                   &completions[i]);
+    grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
+                   do_nothing_end_completion, NULL, &completions[i]);
   }
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -240,8 +240,8 @@
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
     grpc_cq_begin_op(cc, tags[i]);
-    grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
-                   &completions[i]);
+    grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE,
+                   do_nothing_end_completion, NULL, &completions[i]);
   }
 
   for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@@ -294,8 +294,9 @@
 
   gpr_log(GPR_INFO, "producer %d phase 2", opt->id);
   for (i = 0; i < TEST_THREAD_EVENTS; i++) {
-    grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, 1, free_completion,
-                   NULL, gpr_malloc(sizeof(grpc_cq_completion)));
+    grpc_cq_end_op(&exec_ctx, opt->cc, (void *)(intptr_t)1, GRPC_ERROR_NONE,
+                   free_completion, NULL,
+                   gpr_malloc(sizeof(grpc_cq_completion)));
     opt->events_triggered++;
     grpc_exec_ctx_finish(&exec_ctx);
   }
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index de9ba8d..f447a68 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -1,35 +1,35 @@
 /*
-*
-* Copyright 2016, Google Inc.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*
-*     * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-*     * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following disclaimer
-* in the documentation and/or other materials provided with the
-* distribution.
-*     * Neither the name of Google Inc. nor the names of its
-* contributors may be used to endorse or promote products derived from
-* this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*/
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
 
 #include <memory.h>
 #include <stdio.h>
@@ -102,7 +102,7 @@
   (void)acceptor;
   grpc_endpoint_shutdown(exec_ctx, tcp);
   grpc_endpoint_destroy(exec_ctx, tcp);
-  grpc_pollset_kick(args->pollset, NULL);
+  GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
 }
 
 void bad_server_thread(void *vargs) {
@@ -112,10 +112,14 @@
   struct sockaddr_storage addr;
   socklen_t addr_len = sizeof(addr);
   int port;
-  grpc_tcp_server *s = grpc_tcp_server_create(NULL);
+  grpc_tcp_server *s;
+  grpc_error *error = grpc_tcp_server_create(NULL, &s);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   memset(&addr, 0, sizeof(addr));
   addr.ss_family = AF_INET;
-  port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len);
+  error =
+      grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len, &port);
+  GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error));
   GPR_ASSERT(port > 0);
   gpr_asprintf(&args->addr, "localhost:%d", port);
 
@@ -129,7 +133,11 @@
         gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN));
 
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline);
+    if (!GRPC_LOG_IF_ERROR("pollset_work",
+                           grpc_pollset_work(&exec_ctx, args->pollset, &worker,
+                                             now, deadline))) {
+      gpr_atm_rel_store(&args->stop, 1);
+    }
     gpr_mu_unlock(args->mu);
     grpc_exec_ctx_finish(&exec_ctx);
     gpr_mu_lock(args->mu);
@@ -144,7 +152,7 @@
 }
 
 static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset,
-                                  bool success) {
+                                  grpc_error *error) {
   grpc_pollset_destroy(pollset);
   gpr_free(pollset);
 }
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index edd5056..f36f980 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -47,13 +47,14 @@
 
 static void *tag(intptr_t x) { return (void *)x; }
 
-void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
   grpc_transport_op *op = arg;
   GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *op->connectivity_state);
-  GPR_ASSERT(success);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
 }
 
-void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
+void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
 
 void test_transport_op(grpc_channel *channel) {
   grpc_transport_op op;
diff --git a/test/core/surface/sequential_connectivity_test.c b/test/core/surface/sequential_connectivity_test.c
new file mode 100644
index 0000000..2fba392
--- /dev/null
+++ b/test/core/surface/sequential_connectivity_test.c
@@ -0,0 +1,179 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/thd.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+typedef struct test_fixture {
+  const char *name;
+  void (*add_server_port)(grpc_server *server, const char *addr);
+  grpc_channel *(*create_channel)(const char *addr);
+} test_fixture;
+
+#define NUM_CONNECTIONS 1000
+
+typedef struct {
+  grpc_server *server;
+  grpc_completion_queue *cq;
+} server_thread_args;
+
+static void server_thread_func(void *args) {
+  server_thread_args *a = args;
+  grpc_event ev = grpc_completion_queue_next(
+      a->cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(ev.tag == NULL);
+  GPR_ASSERT(ev.success == true);
+}
+
+static void run_test(const test_fixture *fixture) {
+  gpr_log(GPR_INFO, "TEST: %s", fixture->name);
+
+  grpc_init();
+
+  char *addr;
+  gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die());
+
+  grpc_server *server = grpc_server_create(NULL, NULL);
+  fixture->add_server_port(server, addr);
+  grpc_completion_queue *server_cq = grpc_completion_queue_create(NULL);
+  grpc_server_register_completion_queue(server, server_cq, NULL);
+  grpc_server_start(server);
+
+  server_thread_args sta = {server, server_cq};
+  gpr_thd_id server_thread;
+  gpr_thd_options thdopt = gpr_thd_options_default();
+  gpr_thd_options_set_joinable(&thdopt);
+  gpr_thd_new(&server_thread, server_thread_func, &sta, &thdopt);
+
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  grpc_channel *channels[NUM_CONNECTIONS];
+  for (size_t i = 0; i < NUM_CONNECTIONS; i++) {
+    channels[i] = fixture->create_channel(addr);
+
+    gpr_timespec connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(30);
+    grpc_connectivity_state state;
+    while ((state = grpc_channel_check_connectivity_state(channels[i], 1)) !=
+           GRPC_CHANNEL_READY) {
+      grpc_channel_watch_connectivity_state(channels[i], state,
+                                            connect_deadline, cq, NULL);
+      grpc_event ev = grpc_completion_queue_next(
+          cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+      GPR_ASSERT(ev.tag == NULL);
+      GPR_ASSERT(ev.success == true);
+    }
+  }
+
+  grpc_server_shutdown_and_notify(server, server_cq, NULL);
+  gpr_thd_join(server_thread);
+
+  grpc_completion_queue_shutdown(server_cq);
+  grpc_completion_queue_shutdown(cq);
+
+  while (grpc_completion_queue_next(server_cq,
+                                    gpr_inf_future(GPR_CLOCK_REALTIME), NULL)
+             .type != GRPC_QUEUE_SHUTDOWN)
+    ;
+  while (
+      grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL)
+          .type != GRPC_QUEUE_SHUTDOWN)
+    ;
+
+  for (size_t i = 0; i < NUM_CONNECTIONS; i++) {
+    grpc_channel_destroy(channels[i]);
+  }
+
+  grpc_server_destroy(server);
+  grpc_completion_queue_destroy(server_cq);
+  grpc_completion_queue_destroy(cq);
+
+  grpc_shutdown();
+  gpr_free(addr);
+}
+
+static void insecure_test_add_port(grpc_server *server, const char *addr) {
+  grpc_server_add_insecure_http2_port(server, addr);
+}
+
+static grpc_channel *insecure_test_create_channel(const char *addr) {
+  return grpc_insecure_channel_create(addr, NULL, NULL);
+}
+
+static const test_fixture insecure_test = {
+    "insecure", insecure_test_add_port, insecure_test_create_channel,
+};
+
+static void secure_test_add_port(grpc_server *server, const char *addr) {
+  grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
+                                                  test_server1_cert};
+  grpc_server_credentials *ssl_creds =
+      grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
+  grpc_server_add_secure_http2_port(server, addr, ssl_creds);
+  grpc_server_credentials_release(ssl_creds);
+}
+
+static grpc_channel *secure_test_create_channel(const char *addr) {
+  grpc_channel_credentials *ssl_creds =
+      grpc_ssl_credentials_create(NULL, NULL, NULL);
+  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
+                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
+                                {"foo.test.google.fr"}};
+  grpc_channel_args *new_client_args =
+      grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1);
+  grpc_channel *channel =
+      grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL);
+  grpc_channel_args_destroy(new_client_args);
+  grpc_channel_credentials_release(ssl_creds);
+  return channel;
+}
+
+static const test_fixture secure_test = {
+    "secure", secure_test_add_port, secure_test_create_channel,
+};
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+
+  run_test(&insecure_test);
+  run_test(&secure_test);
+}
diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c
index 1e94c5a..02eb432 100644
--- a/test/core/surface/server_test.c
+++ b/test/core/surface/server_test.c
@@ -32,9 +32,13 @@
  */
 
 #include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -86,8 +90,13 @@
   gpr_asprintf(&addr, "[::]:%d", port);
   grpc_server_register_completion_queue(server1, cq, NULL);
   grpc_server_register_completion_queue(server2, cq, NULL);
+  GPR_ASSERT(0 == grpc_server_add_secure_http2_port(server2, addr, NULL));
   GPR_ASSERT(port == grpc_server_add_insecure_http2_port(server1, addr));
   GPR_ASSERT(0 == grpc_server_add_insecure_http2_port(server2, addr));
+  grpc_server_credentials *fake_creds =
+      grpc_fake_transport_security_server_credentials_create();
+  GPR_ASSERT(0 == grpc_server_add_secure_http2_port(server2, addr, fake_creds));
+  grpc_server_credentials_release(fake_creds);
   grpc_server_shutdown_and_notify(server1, cq, NULL);
   grpc_server_shutdown_and_notify(server2, cq, NULL);
   grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
@@ -98,12 +107,68 @@
   gpr_free(addr);
 }
 
+void test_bind_server_to_addr(const char *host, bool secure) {
+  int port = grpc_pick_unused_port_or_die();
+  char *addr;
+  gpr_join_host_port(&addr, host, port);
+  gpr_log(GPR_INFO, "Test bind to %s", addr);
+
+  grpc_server *server = grpc_server_create(NULL, NULL);
+  if (secure) {
+    grpc_server_credentials *fake_creds =
+        grpc_fake_transport_security_server_credentials_create();
+    GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, fake_creds));
+    grpc_server_credentials_release(fake_creds);
+  } else {
+    GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr));
+  }
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  grpc_server_register_completion_queue(server, cq, NULL);
+  grpc_server_start(server);
+  grpc_server_shutdown_and_notify(server, cq, NULL);
+  grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
+  grpc_server_destroy(server);
+  grpc_completion_queue_destroy(cq);
+  gpr_free(addr);
+}
+
+static int external_dns_works(const char *host) {
+  grpc_resolved_addresses *res;
+  grpc_error *error = grpc_blocking_resolve_address(host, "80", &res);
+  GRPC_ERROR_UNREF(error);
+  if (res != NULL) {
+    grpc_resolved_addresses_destroy(res);
+    return 1;
+  }
+  return 0;
+}
+
+static void test_bind_server_to_addrs(const char **addrs, size_t n) {
+  for (size_t i = 0; i < n; i++) {
+    test_bind_server_to_addr(addrs[i], false);
+    test_bind_server_to_addr(addrs[i], true);
+  }
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
   test_register_method_fail();
   test_request_call_on_no_server_cq();
   test_bind_server_twice();
+
+  static const char *addrs[] = {
+      "::1", "127.0.0.1", "::ffff:127.0.0.1", "localhost", "0.0.0.0", "::",
+  };
+  test_bind_server_to_addrs(addrs, GPR_ARRAY_SIZE(addrs));
+
+  if (external_dns_works("loopback46.unittest.grpc.io")) {
+    static const char *dns_addrs[] = {
+        "loopback46.unittest.grpc.io", "loopback4.unittest.grpc.io",
+    };
+    test_bind_server_to_addrs(dns_addrs, GPR_ARRAY_SIZE(dns_addrs));
+  }
+
   grpc_shutdown();
   return 0;
 }
diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
index 1e3d2d3..b7f68e0 100644
--- a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
+++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
@@ -53,7 +53,7 @@
   grpc_chttp2_hpack_parser parser;
   grpc_chttp2_hpack_parser_init(&parser);
   parser.on_header = onhdr;
-  grpc_chttp2_hpack_parser_parse(&parser, data, data + size);
+  GRPC_ERROR_UNREF(grpc_chttp2_hpack_parser_parse(&parser, data, data + size));
   grpc_chttp2_hpack_parser_destroy(&parser);
   grpc_shutdown();
   return 0;
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 51bf48d..9ddceb8 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -76,7 +76,8 @@
 
   for (i = 0; i < nslices; i++) {
     GPR_ASSERT(grpc_chttp2_hpack_parser_parse(
-        parser, GPR_SLICE_START_PTR(slices[i]), GPR_SLICE_END_PTR(slices[i])));
+                   parser, GPR_SLICE_START_PTR(slices[i]),
+                   GPR_SLICE_END_PTR(slices[i])) == GRPC_ERROR_NONE);
   }
 
   for (i = 0; i < nslices; i++) {
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index 73e59f1..98e486c 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -144,7 +144,7 @@
     gpr_asprintf(&key, "K:%d", i);
     gpr_asprintf(&value, "VALUE:%d", i);
     elem = grpc_mdelem_from_strings(key, value);
-    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(elem);
     assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
     gpr_free(key);
@@ -181,13 +181,13 @@
 
   grpc_chttp2_hptbl_init(&tbl);
   elem = grpc_mdelem_from_strings("abc", "xyz");
-  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(elem);
   elem = grpc_mdelem_from_strings("abc", "123");
-  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(elem);
   elem = grpc_mdelem_from_strings("x", "1");
-  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(elem);
 
   r = find_simple(&tbl, "abc", "123");
@@ -238,7 +238,7 @@
   for (i = 0; i < 10000; i++) {
     int64_ttoa(i, buffer);
     elem = grpc_mdelem_from_strings("test", buffer);
-    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(elem);
   }
 
diff --git a/test/core/transport/connectivity_state_test.c b/test/core/transport/connectivity_state_test.c
index 38dea01..1050059 100644
--- a/test/core/transport/connectivity_state_test.c
+++ b/test/core/transport/connectivity_state_test.c
@@ -43,14 +43,15 @@
 
 int g_counter;
 
-static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  GPR_ASSERT(success);
+static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
+                         grpc_error *error) {
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(arg == THE_ARG);
   g_counter++;
 }
 
-static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
-  GPR_ASSERT(!success);
+static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
   GPR_ASSERT(arg == THE_ARG);
   g_counter++;
 }
@@ -67,15 +68,18 @@
       0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_TRANSIENT_FAILURE),
                   "TRANSIENT_FAILURE"));
   GPR_ASSERT(0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_SHUTDOWN),
-                         "FATAL_FAILURE"));
+                         "SHUTDOWN"));
 }
 
 static void test_check(void) {
   grpc_connectivity_state_tracker tracker;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_error *error;
   gpr_log(GPR_DEBUG, "test_check");
   grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx");
-  GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE);
+  GPR_ASSERT(grpc_connectivity_state_check(&tracker, &error) ==
+             GRPC_CHANNEL_IDLE);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   grpc_connectivity_state_destroy(&exec_ctx, &tracker);
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
index 7768413..ed9545e 100644
--- a/test/core/util/mock_endpoint.c
+++ b/test/core/util/mock_endpoint.c
@@ -51,7 +51,7 @@
   gpr_mu_lock(&m->mu);
   if (m->read_buffer.count > 0) {
     gpr_slice_buffer_swap(&m->read_buffer, slices);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb, GRPC_ERROR_NONE, NULL);
   } else {
     m->on_read = cb;
     m->on_read_out = slices;
@@ -65,7 +65,7 @@
   for (size_t i = 0; i < slices->count; i++) {
     m->on_write(slices->slices[i]);
   }
-  grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+  grpc_exec_ctx_sched(exec_ctx, cb, GRPC_ERROR_NONE, NULL);
 }
 
 static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
@@ -78,7 +78,8 @@
   grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
   gpr_mu_lock(&m->mu);
   if (m->on_read) {
-    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, m->on_read,
+                        GRPC_ERROR_CREATE("Endpoint Shutdown"), NULL);
     m->on_read = NULL;
   }
   gpr_mu_unlock(&m->mu);
@@ -115,7 +116,7 @@
   gpr_mu_lock(&m->mu);
   if (m->on_read != NULL) {
     gpr_slice_buffer_add(m->on_read_out, slice);
-    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, m->on_read, GRPC_ERROR_NONE, NULL);
     m->on_read = NULL;
   } else {
     gpr_slice_buffer_add(&m->read_buffer, slice);
diff --git a/test/core/util/one_corpus_entry_fuzzer.c b/test/core/util/one_corpus_entry_fuzzer.c
index be32a8a..95ae4cf 100644
--- a/test/core/util/one_corpus_entry_fuzzer.c
+++ b/test/core/util/one_corpus_entry_fuzzer.c
@@ -34,7 +34,7 @@
 #include <stdbool.h>
 
 #include <grpc/support/log.h>
-#include "src/core/lib/support/load_file.h"
+#include "src/core/lib/iomgr/load_file.h"
 
 extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
@@ -42,11 +42,11 @@
 extern bool leak_check;
 
 int main(int argc, char **argv) {
-  int ok = 0;
+  gpr_slice buffer;
   squelch = false;
   leak_check = false;
-  gpr_slice buffer = gpr_load_file(argv[1], 0, &ok);
-  GPR_ASSERT(ok);
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("load_file", grpc_load_file(argv[1], 0, &buffer)));
   LLVMFuzzerTestOneInput(GPR_SLICE_START_PTR(buffer), GPR_SLICE_LENGTH(buffer));
   gpr_slice_unref(buffer);
   return 0;
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index ae955b1..a39f3dd 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -59,10 +59,11 @@
   half *m = (half *)ep;
   gpr_mu_lock(&m->parent->mu);
   if (m->parent->shutdown) {
-    grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb, GRPC_ERROR_CREATE("Already shutdown"),
+                        NULL);
   } else if (m->read_buffer.count > 0) {
     gpr_slice_buffer_swap(&m->read_buffer, slices);
-    grpc_exec_ctx_enqueue(exec_ctx, cb, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, cb, GRPC_ERROR_NONE, NULL);
   } else {
     m->on_read = cb;
     m->on_read_out = slices;
@@ -79,14 +80,14 @@
                      gpr_slice_buffer *slices, grpc_closure *cb) {
   half *m = other_half((half *)ep);
   gpr_mu_lock(&m->parent->mu);
-  bool ok = true;
+  grpc_error *error = GRPC_ERROR_NONE;
   if (m->parent->shutdown) {
-    ok = false;
+    error = GRPC_ERROR_CREATE("Endpoint already shutdown");
   } else if (m->on_read != NULL) {
     for (size_t i = 0; i < slices->count; i++) {
       gpr_slice_buffer_add(m->on_read_out, gpr_slice_ref(slices->slices[i]));
     }
-    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, true, NULL);
+    grpc_exec_ctx_sched(exec_ctx, m->on_read, GRPC_ERROR_NONE, NULL);
     m->on_read = NULL;
   } else {
     for (size_t i = 0; i < slices->count; i++) {
@@ -94,7 +95,7 @@
     }
   }
   gpr_mu_unlock(&m->parent->mu);
-  grpc_exec_ctx_enqueue(exec_ctx, cb, ok, NULL);
+  grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
 }
 
 static void me_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
@@ -108,12 +109,14 @@
   gpr_mu_lock(&m->parent->mu);
   m->parent->shutdown = true;
   if (m->on_read) {
-    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE("Shutdown"),
+                        NULL);
     m->on_read = NULL;
   }
   m = other_half(m);
   if (m->on_read) {
-    grpc_exec_ctx_enqueue(exec_ctx, m->on_read, false, NULL);
+    grpc_exec_ctx_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE("Shutdown"),
+                        NULL);
     m->on_read = NULL;
   }
   gpr_mu_unlock(&m->parent->mu);
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index f924d55..a5c8c49 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -56,7 +56,7 @@
 } freereq;
 
 static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p,
-                                      bool success) {
+                                      grpc_error *error) {
   grpc_pollset *pollset = grpc_polling_entity_pollset(p);
   grpc_pollset_destroy(pollset);
   gpr_free(pollset);
@@ -64,17 +64,20 @@
 }
 
 static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
-                                   const grpc_httpcli_response *response) {
+                                   grpc_error *error) {
   freereq *pr = arg;
   gpr_mu_lock(pr->mu);
   pr->done = 1;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL);
+  GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
   gpr_mu_unlock(pr->mu);
 }
 
 void grpc_free_port_using_server(char *server, int port) {
   grpc_httpcli_context context;
   grpc_httpcli_request req;
+  grpc_httpcli_response rsp;
   freereq pr;
   char *path;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -84,6 +87,7 @@
 
   memset(&pr, 0, sizeof(pr));
   memset(&req, 0, sizeof(req));
+  memset(&rsp, 0, sizeof(rsp));
 
   grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &pr.mu);
@@ -96,14 +100,18 @@
 
   grpc_httpcli_context_init(&context);
   grpc_httpcli_get(&exec_ctx, &context, &pr.pops, &req,
-                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), freed_port_from_server,
-                   &pr);
+                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+                   grpc_closure_create(freed_port_from_server, &pr), &rsp);
   gpr_mu_lock(pr.mu);
   while (!pr.done) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
+                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
+      pr.done = 1;
+    }
   }
   gpr_mu_unlock(pr.mu);
 
@@ -113,6 +121,7 @@
                         shutdown_closure);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(path);
+  grpc_http_response_destroy(&rsp);
 }
 
 typedef struct portreq {
@@ -122,19 +131,22 @@
   int retries;
   char *server;
   grpc_httpcli_context *ctx;
+  grpc_httpcli_response response;
 } portreq;
 
 static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
-                                 const grpc_httpcli_response *response) {
+                                 grpc_error *error) {
   size_t i;
   int port = 0;
   portreq *pr = arg;
   int failed = 0;
+  grpc_httpcli_response *response = &pr->response;
 
-  if (!response) {
+  if (error != GRPC_ERROR_NONE) {
     failed = 1;
-    gpr_log(GPR_DEBUG,
-            "failed port pick from server: retrying [response=NULL]");
+    const char *msg = grpc_error_string(error);
+    gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
+    grpc_error_free_string(msg);
   } else if (response->status != 200) {
     failed = 1;
     gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
@@ -153,9 +165,12 @@
     pr->retries++;
     req.host = pr->server;
     req.http.path = "/get";
+    grpc_http_response_destroy(&pr->response);
+    memset(&pr->response, 0, sizeof(pr->response));
     grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, &req,
-                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
-                     pr);
+                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+                     grpc_closure_create(got_port_from_server, pr),
+                     &pr->response);
     return;
   }
   GPR_ASSERT(response);
@@ -167,7 +182,9 @@
   GPR_ASSERT(port > 1024);
   gpr_mu_lock(pr->mu);
   pr->port = port;
-  grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL);
+  GRPC_LOG_IF_ERROR(
+      "pollset_kick",
+      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
   gpr_mu_unlock(pr->mu);
 }
 
@@ -194,19 +211,24 @@
   req.http.path = "/get";
 
   grpc_httpcli_context_init(&context);
-  grpc_httpcli_get(&exec_ctx, &context, &pr.pops, &req,
-                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
-                   &pr);
+  grpc_httpcli_get(
+      &exec_ctx, &context, &pr.pops, &req, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+      grpc_closure_create(got_port_from_server, &pr), &pr.response);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_mu_lock(pr.mu);
   while (pr.port == -1) {
     grpc_pollset_worker *worker = NULL;
-    grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
+    if (!GRPC_LOG_IF_ERROR(
+            "pollset_work",
+            grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
+                              &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
+      pr.port = 0;
+    }
   }
   gpr_mu_unlock(pr.mu);
 
+  grpc_http_response_destroy(&pr.response);
   grpc_httpcli_context_destroy(&context);
   grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                         shutdown_closure);
diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c
index e39a957..27c16fc 100644
--- a/test/core/util/test_tcp_server.c
+++ b/test/core/util/test_tcp_server.c
@@ -46,7 +46,7 @@
 #include "test/core/util/port.h"
 
 static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data,
-                                bool success) {
+                                grpc_error *error) {
   test_tcp_server *server = data;
   server->shutdown = 1;
 }
@@ -72,9 +72,12 @@
   addr.sin_port = htons((uint16_t)port);
   memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
 
-  server->tcp_server = grpc_tcp_server_create(&server->shutdown_complete);
-  port_added =
-      grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr));
+  grpc_error *error =
+      grpc_tcp_server_create(&server->shutdown_complete, &server->tcp_server);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  error = grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr),
+                                   &port_added);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(port_added == port);
 
   grpc_tcp_server_start(&exec_ctx, server->tcp_server, &server->pollset, 1,
@@ -91,13 +94,14 @@
                    gpr_time_from_seconds(seconds, GPR_TIMESPAN));
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   gpr_mu_lock(server->mu);
-  grpc_pollset_work(&exec_ctx, server->pollset, &worker,
-                    gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+  GRPC_LOG_IF_ERROR("pollset_work",
+                    grpc_pollset_work(&exec_ctx, server->pollset, &worker,
+                                      gpr_now(GPR_CLOCK_MONOTONIC), deadline));
   gpr_mu_unlock(server->mu);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
 
 void test_tcp_server_destroy(test_tcp_server *server) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index aee866a..e155593 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -807,6 +807,7 @@
 src/core/lib/iomgr/closure.h \
 src/core/lib/iomgr/endpoint.h \
 src/core/lib/iomgr/endpoint_pair.h \
+src/core/lib/iomgr/error.h \
 src/core/lib/iomgr/ev_poll_and_epoll_posix.h \
 src/core/lib/iomgr/ev_poll_posix.h \
 src/core/lib/iomgr/ev_posix.h \
@@ -816,6 +817,7 @@
 src/core/lib/iomgr/iomgr.h \
 src/core/lib/iomgr/iomgr_internal.h \
 src/core/lib/iomgr/iomgr_posix.h \
+src/core/lib/iomgr/load_file.h \
 src/core/lib/iomgr/polling_entity.h \
 src/core/lib/iomgr/pollset.h \
 src/core/lib/iomgr/pollset_set.h \
@@ -903,6 +905,7 @@
 src/core/lib/security/transport/handshake.h \
 src/core/lib/security/transport/secure_endpoint.h \
 src/core/lib/security/transport/security_connector.h \
+src/core/lib/security/transport/tsi_error.h \
 src/core/lib/security/util/b64.h \
 src/core/lib/security/util/json_util.h \
 src/core/lib/tsi/fake_transport_security.h \
@@ -959,6 +962,7 @@
 src/core/lib/iomgr/endpoint.c \
 src/core/lib/iomgr/endpoint_pair_posix.c \
 src/core/lib/iomgr/endpoint_pair_windows.c \
+src/core/lib/iomgr/error.c \
 src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
 src/core/lib/iomgr/ev_poll_posix.c \
 src/core/lib/iomgr/ev_posix.c \
@@ -968,6 +972,7 @@
 src/core/lib/iomgr/iomgr.c \
 src/core/lib/iomgr/iomgr_posix.c \
 src/core/lib/iomgr/iomgr_windows.c \
+src/core/lib/iomgr/load_file.c \
 src/core/lib/iomgr/polling_entity.c \
 src/core/lib/iomgr/pollset_set_windows.c \
 src/core/lib/iomgr/pollset_windows.c \
@@ -1070,6 +1075,7 @@
 src/core/lib/security/transport/secure_endpoint.c \
 src/core/lib/security/transport/security_connector.c \
 src/core/lib/security/transport/server_auth_filter.c \
+src/core/lib/security/transport/tsi_error.c \
 src/core/lib/security/util/b64.c \
 src/core/lib/security/util/json_util.c \
 src/core/lib/surface/init_secure.c \
@@ -1168,7 +1174,6 @@
 src/core/lib/support/backoff.h \
 src/core/lib/support/block_annotate.h \
 src/core/lib/support/env.h \
-src/core/lib/support/load_file.h \
 src/core/lib/support/murmur_hash.h \
 src/core/lib/support/stack_lockfree.h \
 src/core/lib/support/string.h \
@@ -1191,7 +1196,6 @@
 src/core/lib/support/env_windows.c \
 src/core/lib/support/histogram.c \
 src/core/lib/support/host_port.c \
-src/core/lib/support/load_file.c \
 src/core/lib/support/log.c \
 src/core/lib/support/log_android.c \
 src/core/lib/support/log_linux.c \
diff --git a/tools/fuzzer/runners/http_fuzzer_test.sh b/tools/fuzzer/runners/http_request_fuzzer_test.sh
similarity index 95%
copy from tools/fuzzer/runners/http_fuzzer_test.sh
copy to tools/fuzzer/runners/http_request_fuzzer_test.sh
index d8dde14..250a761 100644
--- a/tools/fuzzer/runners/http_fuzzer_test.sh
+++ b/tools/fuzzer/runners/http_request_fuzzer_test.sh
@@ -42,4 +42,4 @@
   flags="-use_traces=1 $flags"
 fi
 
-bins/$config/http_fuzzer_test $flags fuzzer_output test/core/http/corpus
+bins/$config/http_request_fuzzer_test $flags fuzzer_output test/core/http/corpus
diff --git a/tools/fuzzer/runners/http_fuzzer_test.sh b/tools/fuzzer/runners/http_response_fuzzer_test.sh
similarity index 95%
rename from tools/fuzzer/runners/http_fuzzer_test.sh
rename to tools/fuzzer/runners/http_response_fuzzer_test.sh
index d8dde14..f747739 100644
--- a/tools/fuzzer/runners/http_fuzzer_test.sh
+++ b/tools/fuzzer/runners/http_response_fuzzer_test.sh
@@ -42,4 +42,4 @@
   flags="-use_traces=1 $flags"
 fi
 
-bins/$config/http_fuzzer_test $flags fuzzer_output test/core/http/corpus
+bins/$config/http_response_fuzzer_test $flags fuzzer_output test/core/http/corpus
diff --git a/tools/run_tests/performance/kill_workers.sh b/tools/run_tests/performance/kill_workers.sh
index f306f0c..279cc7d 100755
--- a/tools/run_tests/performance/kill_workers.sh
+++ b/tools/run_tests/performance/kill_workers.sh
@@ -39,19 +39,19 @@
 killall -9 qps_worker || true
 
 # C#
-ps -C mono -o pid=,cmd= | grep QpsWorker | awk '{print $1}' | xargs kill -9
+ps -C mono -o pid=,cmd= | grep QpsWorker | awk '{print $1}' | xargs kill -9 || true
 
 # Ruby
-ps -C ruby -o pid=,cmd= | grep 'qps/worker.rb' | awk '{print $1}' | xargs kill -9
+ps -C ruby -o pid=,cmd= | grep 'qps/worker.rb' | awk '{print $1}' | xargs kill -9 || true
 
 # Node
-ps -C node -o pid=,cmd= | grep 'performance/worker.js' | awk '{print $1}' | xargs kill -9
+ps -C node -o pid=,cmd= | grep 'performance/worker.js' | awk '{print $1}' | xargs kill -9 || true
 
 # Python
-ps -C python -o pid=,cmd= | grep 'qps_worker.py' | awk '{print $1}' | xargs kill -9
+ps -C python -o pid=,cmd= | grep 'qps_worker.py' | awk '{print $1}' | xargs kill -9 || true
 
 # Java
-jps | grep LoadWorker | awk '{print $1}' | xargs kill -9
+jps | grep LoadWorker | awk '{print $1}' | xargs kill -9 || true
 
 # Go
 killall -9 worker || true
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 882b349..f5100e8 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -1232,7 +1232,7 @@
         cache=cache if not xml_report else None,
         add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
     if resultset:
-      for k, v in resultset.iteritems():
+      for k, v in sorted(resultset.items()):
         num_runs, num_failures = _calculate_num_runs_failures(v)
         if num_failures == num_runs:  # what about infinite_runs???
           jobset.message('FAILED', k, do_newline=True)
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 4aad52c..57e3bd6 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -557,20 +557,6 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "gpr_load_file_test", 
-    "src": [
-      "test/core/support/load_file_test.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util"
-    ], 
-    "headers": [], 
-    "language": "c", 
     "name": "gpr_log_test", 
     "src": [
       "test/core/support/log_test.c"
@@ -1001,9 +987,9 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "http_fuzzer_test", 
+    "name": "http_parser_test", 
     "src": [
-      "test/core/http/fuzzer.c"
+      "test/core/http/parser_test.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -1017,9 +1003,25 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "http_parser_test", 
+    "name": "http_request_fuzzer_test", 
     "src": [
-      "test/core/http/parser_test.c"
+      "test/core/http/request_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "http_response_fuzzer_test", 
+    "src": [
+      "test/core/http/response_fuzzer.c"
     ], 
     "third_party": false, 
     "type": "target"
@@ -1271,6 +1273,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "load_file_test", 
+    "src": [
+      "test/core/iomgr/load_file_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "low_level_ping_pong_benchmark", 
     "src": [
       "test/core/network_benchmarks/low_level_ping_pong.c"
@@ -1445,6 +1463,22 @@
     ], 
     "headers": [], 
     "language": "c", 
+    "name": "sequential_connectivity_test", 
+    "src": [
+      "test/core/surface/sequential_connectivity_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
     "name": "server_chttp2_test", 
     "src": [
       "test/core/surface/server_chttp2_test.c"
@@ -2710,28 +2744,6 @@
   {
     "deps": [
       "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc++", 
-      "grpc++_test_util", 
-      "grpc_test_util", 
-      "grpc_zookeeper"
-    ], 
-    "headers": [
-      "src/proto/grpc/testing/echo.grpc.pb.h", 
-      "src/proto/grpc/testing/echo.pb.h"
-    ], 
-    "language": "c++", 
-    "name": "zookeeper_test", 
-    "src": [
-      "test/cpp/end2end/zookeeper_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
       "grpc"
     ], 
     "headers": [], 
@@ -4026,9 +4038,26 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
+    "name": "http_request_fuzzer_test_one_entry", 
     "src": [
-      "test/core/http/fuzzer.c", 
+      "test/core/http/request_fuzzer.c", 
+      "test/core/util/one_corpus_entry_fuzzer.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "http_response_fuzzer_test_one_entry", 
+    "src": [
+      "test/core/http/response_fuzzer.c", 
       "test/core/util/one_corpus_entry_fuzzer.c"
     ], 
     "third_party": false, 
@@ -4267,23 +4296,6 @@
   {
     "deps": [
       "gpr", 
-      "grpc"
-    ], 
-    "headers": [
-      "include/grpc/grpc_zookeeper.h"
-    ], 
-    "language": "c", 
-    "name": "grpc_zookeeper", 
-    "src": [
-      "include/grpc/grpc_zookeeper.h", 
-      "src/core/ext/resolver/zookeeper/zookeeper_resolver.c"
-    ], 
-    "third_party": false, 
-    "type": "lib"
-  }, 
-  {
-    "deps": [
-      "gpr", 
       "gpr_test_util", 
       "grpc", 
       "grpc_test_util", 
@@ -5529,7 +5541,6 @@
       "src/core/lib/support/backoff.h", 
       "src/core/lib/support/block_annotate.h", 
       "src/core/lib/support/env.h", 
-      "src/core/lib/support/load_file.h", 
       "src/core/lib/support/murmur_hash.h", 
       "src/core/lib/support/stack_lockfree.h", 
       "src/core/lib/support/string.h", 
@@ -5588,8 +5599,6 @@
       "src/core/lib/support/env_windows.c", 
       "src/core/lib/support/histogram.c", 
       "src/core/lib/support/host_port.c", 
-      "src/core/lib/support/load_file.c", 
-      "src/core/lib/support/load_file.h", 
       "src/core/lib/support/log.c", 
       "src/core/lib/support/log_android.c", 
       "src/core/lib/support/log_linux.c", 
@@ -5712,6 +5721,7 @@
       "src/core/lib/iomgr/closure.h", 
       "src/core/lib/iomgr/endpoint.h", 
       "src/core/lib/iomgr/endpoint_pair.h", 
+      "src/core/lib/iomgr/error.h", 
       "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", 
       "src/core/lib/iomgr/ev_poll_posix.h", 
       "src/core/lib/iomgr/ev_posix.h", 
@@ -5721,6 +5731,7 @@
       "src/core/lib/iomgr/iomgr.h", 
       "src/core/lib/iomgr/iomgr_internal.h", 
       "src/core/lib/iomgr/iomgr_posix.h", 
+      "src/core/lib/iomgr/load_file.h", 
       "src/core/lib/iomgr/polling_entity.h", 
       "src/core/lib/iomgr/pollset.h", 
       "src/core/lib/iomgr/pollset_set.h", 
@@ -5814,6 +5825,8 @@
       "src/core/lib/iomgr/endpoint_pair.h", 
       "src/core/lib/iomgr/endpoint_pair_posix.c", 
       "src/core/lib/iomgr/endpoint_pair_windows.c", 
+      "src/core/lib/iomgr/error.c", 
+      "src/core/lib/iomgr/error.h", 
       "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", 
       "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", 
       "src/core/lib/iomgr/ev_poll_posix.c", 
@@ -5832,6 +5845,8 @@
       "src/core/lib/iomgr/iomgr_posix.c", 
       "src/core/lib/iomgr/iomgr_posix.h", 
       "src/core/lib/iomgr/iomgr_windows.c", 
+      "src/core/lib/iomgr/load_file.c", 
+      "src/core/lib/iomgr/load_file.h", 
       "src/core/lib/iomgr/polling_entity.c", 
       "src/core/lib/iomgr/polling_entity.h", 
       "src/core/lib/iomgr/pollset.h", 
@@ -6162,6 +6177,7 @@
       "src/core/lib/security/transport/handshake.h", 
       "src/core/lib/security/transport/secure_endpoint.h", 
       "src/core/lib/security/transport/security_connector.h", 
+      "src/core/lib/security/transport/tsi_error.h", 
       "src/core/lib/security/util/b64.h", 
       "src/core/lib/security/util/json_util.h"
     ], 
@@ -6207,6 +6223,8 @@
       "src/core/lib/security/transport/security_connector.c", 
       "src/core/lib/security/transport/security_connector.h", 
       "src/core/lib/security/transport/server_auth_filter.c", 
+      "src/core/lib/security/transport/tsi_error.c", 
+      "src/core/lib/security/transport/tsi_error.h", 
       "src/core/lib/security/util/b64.c", 
       "src/core/lib/security/util/b64.h", 
       "src/core/lib/security/util/json_util.c", 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 86f7ea4..833eb88 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -632,27 +632,6 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
-    "name": "gpr_load_file_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
     "name": "gpr_log_test", 
     "platforms": [
       "linux", 
@@ -1357,6 +1336,27 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "load_file_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "message_compress_test", 
     "platforms": [
       "linux", 
@@ -1525,6 +1525,27 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "sequential_connectivity_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "server_chttp2_test", 
     "platforms": [
       "linux", 
@@ -26391,6 +26412,63 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0170e921ff5d052b228a26529116ea47fe9d3f0b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/01a344a0256386cc8abb8dcb65cb55e1244f7f97"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/01c59f0a030fa11c4af1b7c0cc85846e9ef3f6b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/01f52e31dfffdab89d83acd39925c3dd81baa76f"
     ], 
     "ci_platforms": [
@@ -26904,6 +26982,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06b63ac01c261518e291461fb4707cb29d74e9c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/06c714e289673cf982ce2ac0670707a15f2ac5ea"
     ], 
     "ci_platforms": [
@@ -26923,6 +27020,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06eced19ea6819d7b0855c62da49a193b50067ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06eee533524c6723881c1591956edf704e0180d9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07.bin"
     ], 
     "ci_platforms": [
@@ -26999,6 +27134,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0783c943aa7cdb8fdef5f7b1cf73e2bb2daf17f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c"
     ], 
     "ci_platforms": [
@@ -27208,6 +27362,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0963f5f7578c64e9c17d0ad9e4a99ced875cf813"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde"
     ], 
     "ci_platforms": [
@@ -27303,6 +27476,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a90826e3173642be15ea005c2cbe8ca36ac1c3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606"
     ], 
     "ci_platforms": [
@@ -27360,6 +27552,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0b151bf8080f87bd38c9b8521b3b96c40c708463"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0b6f0ea99a329e054032e6c292b99c3bcad0c9f2"
     ], 
     "ci_platforms": [
@@ -27417,6 +27628,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0bf51cb435845a49311a7ddc7341b5cfc8e5ab10"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0c.bin"
     ], 
     "ci_platforms": [
@@ -27607,6 +27837,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0deeaca17aa93f66291407d3d2438685be5b85ba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0def53b5575cc6ab2fbbd17e2bc6a24de9656f84"
     ], 
     "ci_platforms": [
@@ -27626,6 +27875,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0dfd0ea582476b3861106c143c70d7af0f3d1357"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0e.bin"
     ], 
     "ci_platforms": [
@@ -27702,6 +27970,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0e91ce40cf8882adc75b8b532556d48a2b605ced"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0ea509d249ae28faba8980aacb972c7ea28d3fd5"
     ], 
     "ci_platforms": [
@@ -27854,6 +28141,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/10f53c34f02d8c051fe0b8759aec08057433a497"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1109cb814fd134862a3f5ef5c9b2244585882b8f"
     ], 
     "ci_platforms": [
@@ -27873,6 +28179,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/110e019793b395202dfd8b499edc372cdaccff21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/11153bfeee3cdede86a52151dbb939c3ffee48ed"
     ], 
     "ci_platforms": [
@@ -27968,6 +28293,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1239eef13562df4ff59856900eee2f871a2fd0f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1254c9256157e6362003c97c8c93d8cd67a28772"
     ], 
     "ci_platforms": [
@@ -28272,6 +28616,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/15890f893ee7bddcc08f831d684b10d19c369def"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/15c37fe5be9f23c0f0e59e12ee7666007acdb3c5"
     ], 
     "ci_platforms": [
@@ -28462,6 +28825,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1727c0f6369bfb17d1b40ffa3d3f6b8be8a45c62"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/173ebf4139ee6d7a574b6767059d82375674bbf4"
     ], 
     "ci_platforms": [
@@ -28481,6 +28863,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/179817dab786637b3621ace60a9ab4c7c79432a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/17cfb281eaa8a17d77e08c3648bb93f3b5aa5297"
     ], 
     "ci_platforms": [
@@ -28519,6 +28920,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17fa8e029e35c88857b7abcad88609cf2d1ca9a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/17fb35db0b73c331a66120dbc491300b2d1665e0"
     ], 
     "ci_platforms": [
@@ -28557,6 +28977,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1870298c7042983e7716097018a031d105e397fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1887558eb48d6a4341610fd0395cef8e87744044"
     ], 
     "ci_platforms": [
@@ -28633,6 +29072,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1917c5996ac82e13143a414eb9448f171fdd751a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1949f4a75f7d501d5279a01f58a444640379bd78"
     ], 
     "ci_platforms": [
@@ -28652,6 +29110,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/19549ded404f9a9581d32a1827da96ff1420f0ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1972f535ae202777efdd15a09138efc37e07ac01"
     ], 
     "ci_platforms": [
@@ -28766,6 +29243,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b09a1e5994952cda58b8339492f6850936a61f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873"
     ], 
     "ci_platforms": [
@@ -28994,6 +29490,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1cd257e53b8d5a57c9feabcfd9f8f22c30cdb4a8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7"
     ], 
     "ci_platforms": [
@@ -29203,6 +29718,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1fd33a83549fb9fc5e7d05a2c308a044b7c9b167"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1fda93a85f7b5b7a0c2d68a03123e58a6d20f124"
     ], 
     "ci_platforms": [
@@ -29241,6 +29775,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/202a15693f991889b5fdd97f016a5410778b07e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/20322515ebf6df572cb2f596d8a20d3d8893193d"
     ], 
     "ci_platforms": [
@@ -29317,6 +29870,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/20a10c9a0c8cc48fd6317000f70070a0b2451e60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/21357c3613a47180eb668b1c6c849ce9096a46eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2193a1e20caee37676d08c88154a462acf120fb0"
     ], 
     "ci_platforms": [
@@ -29412,6 +30003,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2372fe3d96fda1dae8846a781905c6c408555d3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/23982956d17d2f55e61a5d9111b1c0c7ee530214"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/240afe42d3e2834c46a79d9df0dd6ca018831398"
     ], 
     "ci_platforms": [
@@ -29602,6 +30231,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/25a2c5d4f55a083d2535b46a82e295fb169ffb32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/25aa74daea95f9fc46a78239bd2e78ccf0fb3ffc"
     ], 
     "ci_platforms": [
@@ -29678,6 +30326,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2721f5503254227af744243957ee859fa903e066"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2743ee5a764fb0c4e04cdf84c9b3810ac8093998"
     ], 
     "ci_platforms": [
@@ -29754,6 +30421,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/282003073c8b88d7ad43ce75677777cdb754228c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2837baed2fbf1612f88224e91ddc46241dd9d972"
     ], 
     "ci_platforms": [
@@ -29773,6 +30459,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2858613c057a236dbe306cca44df29232f6b48b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/285b0b9b11fe506527c880d3a866ba94f8038cdf"
     ], 
     "ci_platforms": [
@@ -29887,6 +30592,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/295d24a7705fe1821606f9224f241a7596481bed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/296c3f5b9880fe7ccff4d2a67f489b38b5b6fd6e"
     ], 
     "ci_platforms": [
@@ -29925,6 +30649,63 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a08eb351e08f0e6ac1e1416b43ff962a4e3735c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a1d70b04f4aba0ec93899485f0807a209a4b207"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a2ca2f6a1c03067f87bad61515688edc234bacc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2a410e3d783bc93e63206e28f92b6a40e1db09cf"
     ], 
     "ci_platforms": [
@@ -29963,6 +30744,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2aaee068ca624dcb746af9dc14591b24db033ffc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2ab009994e603404e194ebe0120840d388fb765e"
     ], 
     "ci_platforms": [
@@ -30172,6 +30972,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ce30739d22f5380f96400f261fd26e95cc33927"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589"
     ], 
     "ci_platforms": [
@@ -30343,6 +31162,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2e40d861a9fec3742c31971b583e28bf40e28dbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2e48a9c8d204975060e81f37c7a46ab501750067"
     ], 
     "ci_platforms": [
@@ -30400,6 +31238,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ec78409a7d3625126387512a1c58cae2ff0bcf7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2ef149e8fd68e06fcb7ba2fb43a17cc1dcfd989b"
     ], 
     "ci_platforms": [
@@ -30552,6 +31409,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ffb878075ebb3d2d778c8aabcb0e96cb51060f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3017e9f66dacf5a01f8c7d65b8a72d4f68aa6a28"
     ], 
     "ci_platforms": [
@@ -30647,6 +31523,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30c74b7b5c92bb602d26c3d703c267e288b432a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45"
     ], 
     "ci_platforms": [
@@ -30742,6 +31637,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/31498be283beb45294fb96f15b3af4e7de0ce584"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/314ea0a2c481639b6559b063399299259c43c9bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3152365a4d8540623c9fb3a93712d096bf6b34e6"
     ], 
     "ci_platforms": [
@@ -30761,6 +31694,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/31ef9c4ed85ae1b4e8a027fc5a1d3037dbbf3b3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3230d9876d770657d86dfb768b80494cda52abc8"
     ], 
     "ci_platforms": [
@@ -30818,6 +31770,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/327e5a755e3307b121700f1ba23000a844e70596"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/32a6ea045d1288418617e5e0c52ae02c1f6598aa"
     ], 
     "ci_platforms": [
@@ -30894,6 +31865,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3396a31b1075465bf358eb7836e6f5347a0be591"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3399ac8bb9e0d3a2cbf22a95d1e20c70e2415e41"
     ], 
     "ci_platforms": [
@@ -31027,6 +32017,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/350a1f6d0fe784667d7ae78e1ed783cdf2263bfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/35ba1a4df4d362ea98e9386269bfbb95c5ed4874"
     ], 
     "ci_platforms": [
@@ -31046,6 +32055,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/35cf9a1a6f81db0829d854fd3716916bae081c8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/364f77bffd55805e2be9d2b3a071012e8fc3a083"
     ], 
     "ci_platforms": [
@@ -31103,6 +32131,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/368f9368e43f7e743653d46360836b3db1b1ba8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/36dea0ab5bc764c2eb2f428bcbe2786e64da8bd3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/37309bbfb4f0d78e6138b13a4e5da5944c95b97d"
     ], 
     "ci_platforms": [
@@ -31122,6 +32188,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/376f42635e918cc28706b82ad8923cc7401aa9e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/37bc0646132afe8c79cda5e76de150a473fc0680"
     ], 
     "ci_platforms": [
@@ -31141,6 +32226,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/37cf256347732e86fa92089847b7381e964cc83f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e"
     ], 
     "ci_platforms": [
@@ -31236,6 +32340,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/38eb06643f87fff21483433dc4169e0388b0c9e1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea"
     ], 
     "ci_platforms": [
@@ -31426,6 +32549,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3b114f7e66bf6cbf256a5e656ab6620e3f31277f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3b60e6663ac7ceaa40f91d3a68fcb9c35e3e99b8"
     ], 
     "ci_platforms": [
@@ -31635,6 +32777,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3db644687c6a09fae4267f05b63a969f28024f87"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3dc1bcb27ed0616a2b905025a8898759d94a934d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959"
     ], 
     "ci_platforms": [
@@ -31711,6 +32891,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3f2e5f90e1a93df61a1c9c09b8c9116149eec526"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3f31d328c16207904d201406f7e9708360d5799b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3f36ae935255c4bbd2bd8d4a85bfa92bba02225c"
     ], 
     "ci_platforms": [
@@ -31806,6 +33024,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4141d93d6c387967967844423a6a83ad1793010a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/41921ba00dfc038778074b1af81104555ca74927"
     ], 
     "ci_platforms": [
@@ -32794,6 +34031,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a4675803915c9dafe85b8026c93a0ca9c498233"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21"
     ], 
     "ci_platforms": [
@@ -32965,6 +34221,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d345f45f808c5b0541976b5dff98c603611e9ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4d472e5a8e8ee92be6f23a101babbc601dd2512c"
     ], 
     "ci_platforms": [
@@ -33003,6 +34278,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4d5e7091c1c67867f2760543d9a8a7256007bdef"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4d7b5b98536de248387605efd813ba23b8b613dd"
     ], 
     "ci_platforms": [
@@ -33079,6 +34373,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4e8dbf3eb7d11a4fdb994f281454be2a7ebb091c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4ea18756816848daf5e799ce1d75ecf52353eb08"
     ], 
     "ci_platforms": [
@@ -33098,6 +34411,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4eedb47e422ce761fc5b279582e56c7d1f3ed180"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4ef22ea5b0aa8b80a180a9654f5aef121c5aad83"
     ], 
     "ci_platforms": [
@@ -33231,6 +34563,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5109721ea8f74b08d455968fce90dd74c29aa95a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5151ad7147bbb75b1b377ce03f4ef5ef0f4f1c82"
     ], 
     "ci_platforms": [
@@ -33250,6 +34601,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51be7e2267e32f2eb8079349882f8247dc397d0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/51d7466ac65468db7094bdedc60d1604231acc05"
     ], 
     "ci_platforms": [
@@ -33288,6 +34658,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/521e1e27b0997a0dc168f628e8a0497f7f93ea6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5220909c423d2b321e8459355c965fb330288565"
     ], 
     "ci_platforms": [
@@ -33440,6 +34829,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/541e87b9d3dc75ad40cb47935ed4de83b25af5b9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/543ea879faab347874ad5e297684a62a1555e1ab"
     ], 
     "ci_platforms": [
@@ -33592,6 +35000,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5611060a04db105e03cc74da57352b8a09c411e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8"
     ], 
     "ci_platforms": [
@@ -33630,6 +35057,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/56e0bd235d4ea1de80d753b2b12d03d43cd0aa06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf"
     ], 
     "ci_platforms": [
@@ -33744,6 +35190,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57d4ef9e72f97aa8a1e6689f3be092fc2b24315c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/57da1745490c2f21ecb86370f1f72f77752bc739"
     ], 
     "ci_platforms": [
@@ -33877,6 +35342,63 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5967be7b53e3bac677c726d30a513949e06e1fde"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/598c513564bc043f831876ea61cb8283d43f6726"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/59db3f98b38747d4a35524c1b3d31b5e90f53775"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/59de0a42d012ca3dd8b7fa2f1b1c6642cb86fad4"
     ], 
     "ci_platforms": [
@@ -34105,6 +35627,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5c37a2f980223e737574dba8239378f643800c28"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5c388b60e622e14c9abfb5b46c65207a319e09e4"
     ], 
     "ci_platforms": [
@@ -34333,6 +35874,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ddce6103cb33bc58571c8135b620443740e3646"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a"
     ], 
     "ci_platforms": [
@@ -34352,6 +35912,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5e31ededf3b3189d252148c450de7a8778653e72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5e880db498f9baae544cdbc23476873d8766ac58"
     ], 
     "ci_platforms": [
@@ -34485,6 +36064,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5f61659c332f6153f9a59746bc02064155443b4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5f7eee027cbd6ae8e989150d9bd8a4fd39654c01"
     ], 
     "ci_platforms": [
@@ -34523,6 +36121,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/60ad6847b1fe72ee81decf28dcffa30ce372af6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579"
     ], 
     "ci_platforms": [
@@ -34713,6 +36330,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c"
     ], 
     "ci_platforms": [
@@ -35055,6 +36691,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6619768ddd830ebe29021e827961fddb78751086"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6639deedbf04eceba6017f712b287235540b5528"
     ], 
     "ci_platforms": [
@@ -35188,6 +36843,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/682fdabcfc7243e9c93108d6b2d7d3e920e81970"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6868e669f4b9a77ae5227767ec455fe6f82e55a1"
     ], 
     "ci_platforms": [
@@ -35378,6 +37052,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ad7afcf2d12025faf0e1812ee7a0a5d754620c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ae8b3afc4f6e3a26fec5eaeb2bf64727927552b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6b1e10a936df3b42720ebc9179fb74aa147f8b14"
     ], 
     "ci_platforms": [
@@ -35416,6 +37128,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6be9f2d2967566ac929c27a27de40af792a6da90"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6bfbea131237606756a12f275e736045c0956536"
     ], 
     "ci_platforms": [
@@ -35454,6 +37185,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6c34a6b47ef9e11e02f7675087d888c2c994b010"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6c5707e8b1aa9a70ec87014cd660df4a7b910ee3"
     ], 
     "ci_platforms": [
@@ -35530,6 +37280,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ce0f95767e8b1c58ff313d10f1a3eb1f9ab8496"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ce9895c780428861d12440946508c6641352544"
     ], 
     "ci_platforms": [
@@ -35549,6 +37318,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6cfe000a50ad8b908b3efa3af94c5df6382ff33d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6d6d70df4499b8595851100ffb833d397cc87a18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ded157ecd3fce79fa69c51ee9ecb4639013e6ba"
     ], 
     "ci_platforms": [
@@ -35606,6 +37413,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6e3d43e98d7be45ecc1863eedfeb85a4cae4a007"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6e77e1cd328bb98d954043230716863c5133c1c4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6e97f4e782ca976d4890199d48fcfd64173e24f9"
     ], 
     "ci_platforms": [
@@ -35682,6 +37527,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6f68ff31046fd15930657516873b8835fdbadfe3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6f88ae246aa4af9c74732d87a758ba5ca0f40caf"
     ], 
     "ci_platforms": [
@@ -35967,6 +37831,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71f9eafe17e974062938a6a12433ce723fe07d40"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72160b48e0995ee82f116d77a7fb23a028c10932"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7217d93c1da3ae8ed085a5e6988227dcf430cd89"
     ], 
     "ci_platforms": [
@@ -36309,6 +38211,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/756d77e9fb9ed9dac1db0b1c8cdcc6e05e47329b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/75755ae5cb0ae4f711dd15925f9f681d23408bb8"
     ], 
     "ci_platforms": [
@@ -36347,6 +38268,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7590589db6b56b4e7db9333fba8d723b6461e0a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/75a242a8e6a0c453ac785fe6495d408e9650e17d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302"
     ], 
     "ci_platforms": [
@@ -36575,6 +38534,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/78d8b2a1732c4528d6acdb21c236f417a0f85798"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e"
     ], 
     "ci_platforms": [
@@ -36632,6 +38610,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/79975e5fb34f3569b0d2e40d34d6f7ab1bf82cf2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/79ac297c667d2ae77c05d2af275b05138439ee5b"
     ], 
     "ci_platforms": [
@@ -36689,6 +38686,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7b44a92a28ff5c96be7c4dae5c56a9e5fa272ad3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7b4b493ac5a36d3b3fed0b66bc504206548a3537"
     ], 
     "ci_platforms": [
@@ -36955,6 +38971,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7cfe9fd65c3daa43067dfc99dac2814b763b9f48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7d33039255c9611d0e9e0cc7e230f87ad55c007f"
     ], 
     "ci_platforms": [
@@ -36974,6 +39009,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7d3ff63f0b0019fef80e5e3cd82de8dfbcd07103"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7d6713afac17551fc2628c0f9f18c41a1aa9c2f1"
     ], 
     "ci_platforms": [
@@ -37145,6 +39199,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7f2a2a365669c88559036ed998b074b1b9a31e0b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7fe7a6ab57422c40c7e0e2333c3bbb6ae6a0d9a3"
     ], 
     "ci_platforms": [
@@ -37278,6 +39351,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/81437c61aeca9becc91003af7b835dc65a3e03e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/81489a0c6a71c48e9f343cb5ff8e8b5693d5df19"
     ], 
     "ci_platforms": [
@@ -37392,6 +39484,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8272e45483cb4cc7113b0ffad71f9218542f9cd7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a"
     ], 
     "ci_platforms": [
@@ -37430,6 +39541,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/83e2bd562704e16ac57589b4273d0c61775d7c9c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/840928fe62714fdb003b3f0a40c2c4897f9d7938"
     ], 
     "ci_platforms": [
@@ -37449,6 +39579,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/84505278558cc406dc36109deab239f1e4cf1518"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/84650393df0dca7ca3244faa7ac036873d3dcce1"
     ], 
     "ci_platforms": [
@@ -37525,6 +39674,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8525fa2b11288eda66418be4ecfcf8d7731d75a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e"
     ], 
     "ci_platforms": [
@@ -37563,6 +39731,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/85a50177266a832eca0563d37ccb03890f12c665"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/85afba0cb1eb440ed95ee5793a70c7e5d8465148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/85bd45792a3cf2116fab5e99e2d824ee804af843"
     ], 
     "ci_platforms": [
@@ -37582,6 +39788,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/871196ccb877b7c6c7d6cafe3324fde440706de3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8711e2f477871e3ca68642bbb388e7f473f25394"
     ], 
     "ci_platforms": [
@@ -37905,6 +40130,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a13b47235d2967f5a5419cb0ad8d241a750a365"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7"
     ], 
     "ci_platforms": [
@@ -37924,6 +40168,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8a6ccd18dbc530ed34afd4a73beeff0449040c25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8a912877743b165b233303efaf502f5092b3c5b0"
     ], 
     "ci_platforms": [
@@ -38133,6 +40396,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8bdd4dc6dee56fb6965655425ca378f784a42b6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681"
     ], 
     "ci_platforms": [
@@ -38209,6 +40491,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c6776521d0f100708ecb9f8504e572d586b8a21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8d386a409662ef68370c0c552742bd0ea6d527d5"
     ], 
     "ci_platforms": [
@@ -38323,6 +40624,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8de197bbdf4deaea5bd21af25c0b5c5f03b231ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8e226a7f67b7c6e9d439c3627bfa5644af992593"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc"
     ], 
     "ci_platforms": [
@@ -38532,6 +40871,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7"
     ], 
     "ci_platforms": [
@@ -38589,6 +40947,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92882ccad7fc3e7bc1df7dfa5954a6d591d5dbc2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/929980ce480ca47855bdebb8f6ebef7fa447fd5b"
     ], 
     "ci_platforms": [
@@ -38608,6 +40985,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92a87c7a2f2e336f92529bc40deee614dd8b4486"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805"
     ], 
     "ci_platforms": [
@@ -38627,6 +41023,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92e8c16eb9a816c5944ecb76cf9af08f05930aeb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/92ec3b6722dde442121b3d1ed3ef23976c72cba8"
     ], 
     "ci_platforms": [
@@ -38646,6 +41061,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9345e2de4f0476428d941c53013535fbda8a2bca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9379dd6ade6947a59a1786435a2d55a705161ae5"
     ], 
     "ci_platforms": [
@@ -38931,6 +41365,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97539b673cb482cfa4d876df515270611b28f22a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/976613cb09127a752d628c4a3cf73b8e3168e0af"
     ], 
     "ci_platforms": [
@@ -39292,6 +41745,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9b014aa18fb8c033458b6d5fdb351e60d16e8bce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9b5b436057dfcf4299e52ad49c74e45ef04be7a2"
     ], 
     "ci_platforms": [
@@ -39330,6 +41802,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9bbb726cd811fce33aecdbcce3d287c252ed71d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9bc5b4a9a81905cbc7ee4a25482068dcab93898d"
     ], 
     "ci_platforms": [
@@ -39539,6 +42030,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9dd5d09e1538e12b091c35d252ee43684d0f07bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf"
     ], 
     "ci_platforms": [
@@ -39710,6 +42220,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9fd5c58979d17905e46ee7b76f542f7acb54d60f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a001745aa3499a11bf1cee1af077bdc85a03ef95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a074a30fc5c627e8093a8f860d67661df22f8148"
     ], 
     "ci_platforms": [
@@ -39767,6 +42315,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a151b36f390273fb440d2e35ab93acc5540bfed6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a18ed3861270cd42a661211d9d970c488fed46ad"
     ], 
     "ci_platforms": [
@@ -39786,6 +42353,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a19cc971908189b5febf6fb5e8578c91dd666715"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b04c2504a75f50d47875bd1db804cef3674cf0"
     ], 
     "ci_platforms": [
@@ -39805,6 +42391,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b0fdbc2160dfe8c1eed409eb60042c819a843a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a1b153e4cde45a7302094f6c751e3248d2f0fb8e"
     ], 
     "ci_platforms": [
@@ -39938,6 +42543,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a36a34472604c8107353872e77a84873ff8a9170"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a380f7e56171dc69269afb6364216bc69925eb8a"
     ], 
     "ci_platforms": [
@@ -40033,6 +42657,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a3fcf35a54c8c88b5cc1ef76e43124bb25b61ba3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a41e8b175a837b55e540874c3f056a9d9535866c"
     ], 
     "ci_platforms": [
@@ -40052,6 +42695,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a44288607b76ce6df9fe7e196138a587cf4badc9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a4d41bf7bce38a255a431912f6b57637645221e8"
     ], 
     "ci_platforms": [
@@ -40242,6 +42904,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a7ccc1f7db49512983fe4d42c16b2160357e3585"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a7d45318db68aea203c6f661f571394b649cfd86"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a8115b0be87517139447c9fefc33e225f2efdf32"
     ], 
     "ci_platforms": [
@@ -40261,6 +42961,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a8b5f205a578696697bc1ca381e73501c3a9b185"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a8d353c157cc3788a86a0d572adcc7744e7e902a"
     ], 
     "ci_platforms": [
@@ -40375,6 +43094,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa0c7fda7faff932bf36e10d15ab2180ab1bca27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315"
     ], 
     "ci_platforms": [
@@ -40660,6 +43398,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/acd5d85336bff9b38196c682864dd7a4965ac904"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ad6369d2c51c4787778ff9dbd86cc6df44312f1d"
     ], 
     "ci_platforms": [
@@ -40831,6 +43588,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b06102e16c740796a9d30e07b9e564b65f7513da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315"
     ], 
     "ci_platforms": [
@@ -40869,6 +43645,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b1e28018e26e6baaba5a907e5e6ff9b7a7942018"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c"
     ], 
     "ci_platforms": [
@@ -40964,6 +43759,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b2c5f4f8e2129a4201b2525cba8723241bbd8c79"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b2f450dc86671548200a1fe6ee0ee76171edc578"
     ], 
     "ci_platforms": [
@@ -41154,6 +43968,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b4b8ba878466fc6c4e1939e38c38aa64026b055b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b4dfbd50da81516e8afcd93def813b4b813c3ae1"
     ], 
     "ci_platforms": [
@@ -41173,6 +44006,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b4f6d203097dcd1778f4a912cdc3af96ffb681de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157"
     ], 
     "ci_platforms": [
@@ -41192,6 +44044,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b51db02b904ceee344fe48179d0c784c59ca2934"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304"
     ], 
     "ci_platforms": [
@@ -41306,6 +44177,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b63da75ca24aac41285dd14de6712179a3fbc0d1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b6694ec2d425e8ce6ad9ff712a999fabfa5ce113"
     ], 
     "ci_platforms": [
@@ -41344,6 +44234,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b6ce8604e3c14c6867cd2a78cef144ddd2fbb4c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b766e4a3e84ee0a2f57fccbc3a7f7f812b2032d3"
     ], 
     "ci_platforms": [
@@ -41401,6 +44310,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b79553c903c06619d53395ee67896c1554def055"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b7c3f40ef32cd843e331fb49521c0d614dfbecc9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b7d02f4d12cd0b5442a04675e69f98fbdabc775a"
     ], 
     "ci_platforms": [
@@ -41496,6 +44443,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8bedb9c38fd149bc494a65674a4af5e61dfb311"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b8cd185f946c392f8fb5adca4851043df849ac6e"
     ], 
     "ci_platforms": [
@@ -41705,6 +44671,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b9eb50c5eb99cf0b419efa2cb8d7fdf2e71f6634"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ba3d174125e7378292fcbad9bfe8129dabf88b3a"
     ], 
     "ci_platforms": [
@@ -41724,6 +44709,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ba46bf502f75c1e66fb89e18c270da8e5a62207f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/baab31938837e1a3cb49ca12fb886fcbb7d48501"
     ], 
     "ci_platforms": [
@@ -41838,6 +44842,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bb74226288b9d3a163029a25857bbebe84227222"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bba4073cde10ba7abaac18d6303e310d02a47826"
     ], 
     "ci_platforms": [
@@ -42256,6 +45279,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bdfa6991c33f312c46ac27bdd8089be1670f0ac2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/be0ccf7b9b4581e01a42e9cad6343c93ccf6f362"
     ], 
     "ci_platforms": [
@@ -42427,6 +45469,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bf5923216eb069edaf4e135ab7ee426c04d99a25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005"
     ], 
     "ci_platforms": [
@@ -42484,6 +45545,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c09288284e4859b8a85421b19d3c6d0109cdab08"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c0bb5f00fc14ea4f2000f75e6d1d94f23e6203f6"
     ], 
     "ci_platforms": [
@@ -43073,6 +46153,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c77bd1e9d9be2b6d1362cbb15f63cf749aa113ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c7c13a37189ce2482f5517f6ef0903431194e11b"
     ], 
     "ci_platforms": [
@@ -43111,6 +46210,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c845faac6d4b713a232aa3a6749afdf4e58d7f6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c8b5d9fdb7ade3538abb794a3231d5777a1640a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c8f0972dabb904bc6d35ed576fc9a49eb2ed5273"
     ], 
     "ci_platforms": [
@@ -43282,6 +46419,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ca5a1e4fccc55aa977b841d8d67e6991a4371860"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ca6add6699d063e2212335264ad3e004327afc1a"
     ], 
     "ci_platforms": [
@@ -43434,6 +46590,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4272fec464c45438dce72eb9381971ed0207de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048"
     ], 
     "ci_platforms": [
@@ -43472,6 +46647,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd7cf401276531cea7e4221f249f527f231a5bcb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cdc064f39a9a67210b1be6b195d38d5d0d73eaa0"
     ], 
     "ci_platforms": [
@@ -43529,6 +46723,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cea57d6a128cc7cd195cb2390bfde28047d6acf8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e"
     ], 
     "ci_platforms": [
@@ -43719,6 +46932,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-40e0fcf83e934a4ea2d31c009e9dfc1e68f11f3a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-482e9bdce0e13df2a77eef75a1c07d38ee28f4ab"
     ], 
     "ci_platforms": [
@@ -44308,6 +47540,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d02fb86e7e236a2253a2eadb0599f5dc261e4048"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d0692d73e38ed8c154ebddd627ce99890a1cf798"
     ], 
     "ci_platforms": [
@@ -44327,6 +47578,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d07965987a51541498871433e0fc6313884569d3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d079f5c8a10611dc655cef33f73100f5f43787a8"
     ], 
     "ci_platforms": [
@@ -44479,6 +47749,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d19a252c00c74403389fe9e057cffeee39a4d2e0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d1ade96319d9de82cf3b0480d226a5ad9f31eaa1"
     ], 
     "ci_platforms": [
@@ -44517,6 +47806,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d1d35a1d2148c62c6021479d4153e65511b33cc1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d22287b96b3dcb840fc65e4be60e409fb0f6bfe5"
     ], 
     "ci_platforms": [
@@ -44593,6 +47901,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d29cf6979d8d58b4cb779a629ebee62d7e42fc9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6"
     ], 
     "ci_platforms": [
@@ -44707,6 +48034,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d425e534ec074932b5cf4dc9a6cf4fc0683fd690"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d48a5cefe695d0494df4540ea395dcdd90a332ef"
     ], 
     "ci_platforms": [
@@ -44821,6 +48167,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d5d704fdb985efb36fb42f9ee8482ae473bb4695"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4"
     ], 
     "ci_platforms": [
@@ -44916,6 +48281,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d6d7dc448cc24272ce216dbc7365ebe6e6b7b367"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d712d007679af5438c7bda723ddc724c2e57b0c1"
     ], 
     "ci_platforms": [
@@ -44973,6 +48357,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d85482b6a40d7edee97709df0ed02558dca4c079"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d87b7bcd1b05a2f8cc04a2aadb999bcf65b84911"
     ], 
     "ci_platforms": [
@@ -45030,6 +48433,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d8f08b0e061e86e94650aa16f99cae81cd696ca3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d913cc4e8f2900d7035d196fd62707cf1194e02b"
     ], 
     "ci_platforms": [
@@ -45296,6 +48718,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dbcaf0a6bd4960e8d0c518494b89bd9b941cfc8e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dc38c75bcb7df7e61428d8f12ff01a1ec1b68a99"
     ], 
     "ci_platforms": [
@@ -45372,6 +48813,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ddc34d5e97ac12572e6c39a336d219d91fa992b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb"
     ], 
     "ci_platforms": [
@@ -45410,6 +48870,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ddf932a29b8250746ec310af224f95d4a51cb745"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120"
     ], 
     "ci_platforms": [
@@ -45809,6 +49288,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e16a0f378b50b28dae4458b795c8c80cf869901a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e18816dbe46249fb0160b8f06c2b71f6943d3d21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e192ba28f8a3bc9079b810c46ecc526f84609863"
     ], 
     "ci_platforms": [
@@ -46322,6 +49839,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e7d4357e2c3ac4db7a9bfece1549f0664e4d317b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e80302182fbd464b72d2b9be495901c0c3e93344"
     ], 
     "ci_platforms": [
@@ -46360,6 +49896,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e8b1814f9a0942322aeb190ae0ad35105784e101"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e8bc4c1b1ffb23de5af2c8fe20599c05f94567ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e8c24e95b095fee6053a49f51326479b60949424"
     ], 
     "ci_platforms": [
@@ -46474,6 +50048,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ea421a728134ad3a95a32f081c2bafa9d989836f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ea6cc4b0a83ac8d578c4927f3c9d5a57a4464df3"
     ], 
     "ci_platforms": [
@@ -46512,6 +50105,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eab5589ebcdd4596996f0a6de6408a0f3e13437b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/eb342f6fd92411d7beb1f82983a19849d45ff46f"
     ], 
     "ci_platforms": [
@@ -46664,6 +50276,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ec56dad56975e8279b2b229288dff3bb0ceaf661"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ec97d4ee730261bdc3b14349a3346fd45929bd17"
     ], 
     "ci_platforms": [
@@ -46740,6 +50371,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ed913deced10ab045fe04c783f6a0e2678f1929f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ed9a1a597bad76e9ed9e52ba2e5c80304583c006"
     ], 
     "ci_platforms": [
@@ -46816,6 +50466,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad"
     ], 
     "ci_platforms": [
@@ -46968,6 +50637,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f060953b52fe245eb88ee13b32a3971eaa11e40a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f0649728d5f9e1a91735eaa429605ce0da6c00c0"
     ], 
     "ci_platforms": [
@@ -47215,6 +50903,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f2ee773064f643871134a017d35fd5d8ae74d35c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f2f014c6ef70e40f9334096f34584ea4f1f882d7"
     ], 
     "ci_platforms": [
@@ -47253,6 +50960,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f38d6347f6044dbc3978ef7e5d5adfb7fc8aceb9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b"
     ], 
     "ci_platforms": [
@@ -47310,6 +51036,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f4b66d285bd0328e511625b1c696662a0b0b2e70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f4d74d507a7171e5f116bf750a20435eeaf81f3f"
     ], 
     "ci_platforms": [
@@ -47462,6 +51207,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f6d8d78857d868c2f477da7506a1976354f2631d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f71de0dac54e25fe658e8c78208b855d3f0db23c"
     ], 
     "ci_platforms": [
@@ -47956,6 +51720,44 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb263a744a6d40e183e84ec8a81ca13859c8b5ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb324303c6d5819d6f353f78d087e29adba51836"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fb9505e4511c982f4f26675979a138a3408d80e2"
     ], 
     "ci_platforms": [
@@ -47994,6 +51796,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fbc7dd3fbb6abc462ab0493bfe3a8505f12fe4a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fbeb44db0fc0f6b70c226053448c7170f62543b1"
     ], 
     "ci_platforms": [
@@ -48108,6 +51929,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fcc42c56cb8847716474703b5a650f41dce98b38"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda"
     ], 
     "ci_platforms": [
@@ -48279,6 +52119,25 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ff7f9df969df7fe6c9c1515528404b55f9d237b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ff8ffcfafaf420d6fee1cfa087204975ab8e14d6"
     ], 
     "ci_platforms": [
@@ -63764,1355 +67623,6 @@
   }, 
   {
     "args": [
-      "test/core/http/corpus/0299ca2580e4398d170c4a336e0c33eb2cd9d427"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/05e613853d64a9669ea3cf41b0de777dc24931ba"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/069352518a1d1baa05f317c677d275cefda2ac97"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/0925527c9358b1e10ec0f0387cd99f35204d9a34"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/0c5b7c2569410b526605e308309a7f36574e530d"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/0ef3d0a84360bb5ad66274f1226f5cb273ecdbcf"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/1e1273f90187fdf5df3625764245610f86af6aa4"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/1fbc57d118f3733287e9a9d808bb8947b3260e55"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/24756c396bc72894fd720092bb6f9c03e66b469f"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/276def41311933421ae7a9ee42e906c85b6a4d3f"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/29daa75432381937fd005cb25e314e328de6e9f9"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/2a75204bc492084ad853682f8de3fb137d5907bc"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/2d34ba249b755a880525cf53c665633a5e359305"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/33f4ea0c7ea27c37d8f95cfa64d282370efdafd2"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/35554617ea6418bd43161fe9a2c337ed82d7ec5b"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/35f0c561297cfc840ddaeebb9fc61091f4eadece"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/3787bcc22ef645e665cc5f722b8a633af86de9cf"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/3953688866ccb3b4f371f1a858570d6afdb6452d"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/39b19c41ba537f37511eff7727733715db432e76"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/3e3c4756d5e40b5aa250954cbac86b826e70a7ac"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/3f03265921120c6ffa61b944e213e062a5538d4b"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/3fb034e66ee5494a67acae1b4e6ff64ba92a2046"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/466059ed07a0d55d6ad5e522c7d367cbf278eaf9"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/487725eb38511c79a9340bf4560a1411061fa6fa"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/48b9b205cae8ac21512a3f26f49fd53e21ee13c5"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/4b1f1f79a0bfa3f942479dd5f8edb59a7c257c55"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5028c56a5116a186b7343ff59567b47347a0796d"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/533f62b3f495ce704babf3ee8d840f196a714dff"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5892cbb284771fc9761caae37b19cd6e27dbc104"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5aeab6e4f7c2a1c09d4ac0dbdb3beac4893607ee"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5b6292bdf009b0daecbc90b85cca30a88c36eec5"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5c1659b77678b41faa4fa13df7772dae3238d1c0"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/5c81f61621e29ec9c6a64ac3af9b3b216141618e"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/657368df512ca6294b9df16adf935a3f374a8be2"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/7fc4520094902ce2c760d70eaad5b674d2817337"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/81f59a12b458ec3604035cb962165c604d1355e6"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/8f41c50e88ee8c17ecad3d41d63d38fb12aca0b9"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/97c16de7fe3c390a2e6c09ff5c28f17d5c67542c"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/97e4499d450c95660de86747f527e670f2012548"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/9a996857196e0998a1278994a9bab3d35526e7f1"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/9b7e00049ec356ecd84b1747e4e1941140139ae8"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/9f0c38ec455cc363369b3674a2d32bc21c206de1"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/a1dc7bc235e46eb21d91084d7b52d5ff9f45df85"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/aa3bbb876eafa8ad8ca4ff2eabc6dd94341d2441"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/ae8ba95d7dbe99926a8f5bfd80347fd6a4b616a0"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/b04fea5c041c707db0ad9c09a81672557b52cc47"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/c4acff8aa2ff886f35439f72625d05002990c940"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/c55ce9995b002e88a102ae2891a71e8bacb346c8"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/ca5a0c00b8969310acb73d15ad0d0c602f1bd0c2"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/cce734f1b263de6994f7950e0df7bf0c81449f70"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/d39c8ee11a697634a09b309460c0bbd967e7effa"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/d4c3e4cf5d035596433c30eaabbd2b2925f4b453"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/d51f7fcc089f269c7afecaaca51966bab5fde629"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/d936dad71c129cf659097dc3db64550c4dd467f4"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/e275b0466a8fb8d9e0e15856e343ddc7112ae66b"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/e5c364b205855a2991ce07482aebb2a3a6147089"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/ee2077e08c3cfccd9bd82adb574ac4fc7d429afb"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/fdeb2c7daa9e7704f67e141106384e6dd0042c0b"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/request1.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/request2.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/request3.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/request4.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/request5.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response1.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response2.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response3.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response4.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response5.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/response6.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
-      "test/core/http/corpus/toolong.txt"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [
-      "tsan"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "http_fuzzer_test_one_entry", 
-    "platforms": [
-      "linux"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [
       "test/core/json/corpus/006d552e952c42b5340baaeb85c2cb80c81e78dd"
     ], 
     "ci_platforms": [
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 3a214a4..a847add 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -345,15 +345,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_load_file_test", "vcxproj\test\gpr_load_file_test\gpr_load_file_test.vcxproj", "{B36DE5B4-8B73-1194-7539-974D9524D609}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_log_test", "vcxproj\test\gpr_log_test\gpr_log_test.vcxproj", "{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1130,6 +1121,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "load_file_test", "vcxproj\test\load_file_test\load_file_test.vcxproj", "{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "message_compress_test", "vcxproj\test\message_compress_test\message_compress_test.vcxproj", "{07170557-CCB0-D23C-8018-C2909D115DF9}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1216,6 +1218,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sequential_connectivity_test", "vcxproj\test\sequential_connectivity_test\sequential_connectivity_test.vcxproj", "{F164F666-C866-D607-E1DF-E7BF3CF98255}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_chttp2_test", "vcxproj\test\server_chttp2_test\server_chttp2_test.vcxproj", "{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1975,22 +1988,6 @@
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|Win32.Build.0 = Release|Win32
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|x64.ActiveCfg = Release|x64
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|x64.Build.0 = Release|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|Win32.ActiveCfg = Debug|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|x64.ActiveCfg = Debug|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|Win32.ActiveCfg = Release|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|x64.ActiveCfg = Release|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|Win32.Build.0 = Debug|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|x64.Build.0 = Debug|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|Win32.Build.0 = Release|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|x64.Build.0 = Release|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|x64.Build.0 = Debug|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|Win32.Build.0 = Release|Win32
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|x64.ActiveCfg = Release|x64
-		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|x64.Build.0 = Release|x64
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Debug|Win32.ActiveCfg = Debug|Win32
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Debug|x64.ActiveCfg = Debug|x64
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release|Win32.ActiveCfg = Release|Win32
@@ -3127,6 +3124,22 @@
 		{62D58A08-3B5E-D6A8-ABBB-77995AA0A8C6}.Release-DLL|Win32.Build.0 = Release|Win32
 		{62D58A08-3B5E-D6A8-ABBB-77995AA0A8C6}.Release-DLL|x64.ActiveCfg = Release|x64
 		{62D58A08-3B5E-D6A8-ABBB-77995AA0A8C6}.Release-DLL|x64.Build.0 = Release|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug|Win32.ActiveCfg = Debug|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug|x64.ActiveCfg = Debug|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release|Win32.ActiveCfg = Release|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release|x64.ActiveCfg = Release|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug|Win32.Build.0 = Debug|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug|x64.Build.0 = Debug|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release|Win32.Build.0 = Release|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release|x64.Build.0 = Release|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Debug-DLL|x64.Build.0 = Debug|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|Win32.Build.0 = Release|Win32
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|x64.ActiveCfg = Release|x64
+		{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|x64.Build.0 = Release|x64
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Debug|Win32.ActiveCfg = Debug|Win32
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Debug|x64.ActiveCfg = Debug|x64
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Release|Win32.ActiveCfg = Release|Win32
@@ -3255,6 +3268,22 @@
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|Win32.Build.0 = Release|Win32
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.ActiveCfg = Release|x64
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.Build.0 = Release|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug|x64.ActiveCfg = Debug|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release|Win32.ActiveCfg = Release|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release|x64.ActiveCfg = Release|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug|Win32.Build.0 = Debug|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug|x64.Build.0 = Debug|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release|Win32.Build.0 = Release|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release|x64.Build.0 = Release|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Debug-DLL|x64.Build.0 = Debug|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release-DLL|Win32.Build.0 = Release|Win32
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release-DLL|x64.ActiveCfg = Release|x64
+		{F164F666-C866-D607-E1DF-E7BF3CF98255}.Release-DLL|x64.Build.0 = Release|x64
 		{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|Win32.ActiveCfg = Debug|Win32
 		{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|x64.ActiveCfg = Debug|x64
 		{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index 2e403c2..db8594e 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -195,7 +195,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\backoff.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\block_annotate.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h" />
@@ -235,8 +234,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\host_port.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\load_file.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log_android.c">
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index c952a78..9bab373 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -46,9 +46,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\host_port.c">
       <Filter>src\core\lib\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\load_file.c">
-      <Filter>src\core\lib\support</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\support\log.c">
       <Filter>src\core\lib\support</Filter>
     </ClCompile>
@@ -281,9 +278,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h">
       <Filter>src\core\lib\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\load_file.h">
-      <Filter>src\core\lib\support</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h">
       <Filter>src\core\lib\support</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index ec0c984..84e03f7 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -316,6 +316,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
@@ -325,6 +326,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
@@ -412,6 +414,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\b64.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\fake_transport_security.h" />
@@ -488,6 +491,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
@@ -506,6 +511,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
@@ -710,6 +717,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 273f73b..0f817e0 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -55,6 +55,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -82,6 +85,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -388,6 +394,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c">
       <Filter>src\core\lib\security\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\util\b64.c">
       <Filter>src\core\lib\security\util</Filter>
     </ClCompile>
@@ -689,6 +698,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -716,6 +728,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -977,6 +992,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h">
       <Filter>src\core\lib\security\transport</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\b64.h">
       <Filter>src\core\lib\security\util</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index bba099d..ac9bb18 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -305,6 +305,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
@@ -314,6 +315,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
@@ -456,6 +458,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
@@ -474,6 +478,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 78a8777..1341474 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -58,6 +58,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -85,6 +88,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
       <Filter>src\core\lib\iomgr</Filter>
     </ClCompile>
@@ -599,6 +605,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -626,6 +635,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters
deleted file mode 100644
index 0edd0fe..0000000
--- a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\support\load_file_test.c">
-      <Filter>test\core\support</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{7defb822-a4cc-a221-8900-1041a6c2c134}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{3f3cae49-1efd-7015-0fa1-5621168945d5}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\support">
-      <UniqueIdentifier>{54e9b9b9-021a-139b-53f2-2f8b7173306c}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj b/vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj
similarity index 94%
rename from vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
rename to vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj
index 4182969..52fbccc 100644
--- a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
+++ b/vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj
@@ -20,7 +20,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{B36DE5B4-8B73-1194-7539-974D9524D609}</ProjectGuid>
+    <ProjectGuid>{DC76C089-0D55-DF19-7CCA-49DAE5D29E49}</ProjectGuid>
     <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
     <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
   </PropertyGroup>
@@ -60,14 +60,14 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>gpr_load_file_test</TargetName>
+    <TargetName>load_file_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
     <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>gpr_load_file_test</TargetName>
+    <TargetName>load_file_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
@@ -158,10 +158,16 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\support\load_file_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\load_file_test.c">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
       <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
     </ProjectReference>
diff --git a/vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj.filters b/vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj.filters
new file mode 100644
index 0000000..2c7934b
--- /dev/null
+++ b/vsprojects/vcxproj/test/load_file_test/load_file_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\load_file_test.c">
+      <Filter>test\core\iomgr</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{2d5b633c-62d3-3391-6d61-6521bf33e82d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{30d9062f-1ea2-7ee4-249c-0e4220cb5153}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\iomgr">
+      <UniqueIdentifier>{a23b62a8-d5fc-3114-9aa2-8065e49214e8}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj b/vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj
similarity index 94%
copy from vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
copy to vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj
index 4182969..2367b3e 100644
--- a/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
+++ b/vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj
@@ -20,7 +20,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{B36DE5B4-8B73-1194-7539-974D9524D609}</ProjectGuid>
+    <ProjectGuid>{F164F666-C866-D607-E1DF-E7BF3CF98255}</ProjectGuid>
     <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
     <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
   </PropertyGroup>
@@ -60,14 +60,14 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>gpr_load_file_test</TargetName>
+    <TargetName>sequential_connectivity_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
     <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>gpr_load_file_test</TargetName>
+    <TargetName>sequential_connectivity_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
@@ -158,10 +158,16 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\support\load_file_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\surface\sequential_connectivity_test.c">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
       <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
     </ProjectReference>
diff --git a/vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj.filters b/vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj.filters
new file mode 100644
index 0000000..e2b0d03
--- /dev/null
+++ b/vsprojects/vcxproj/test/sequential_connectivity_test/sequential_connectivity_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\surface\sequential_connectivity_test.c">
+      <Filter>test\core\surface</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{432df9fa-0f9a-912a-8413-adc38d9c27ca}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{42030451-0f78-add5-87be-b81131bcc0f5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\surface">
+      <UniqueIdentifier>{34047576-8f8d-eeb2-d596-35be59941f62}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+