diff --git a/MODULE.bazel b/MODULE.bazel
index 88f3a524060..e62ec70dda0 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -2,7 +2,7 @@ module(
     name = "grpc-java",
     compatibility_level = 0,
     repo_name = "io_grpc_grpc_java",
-    version = "1.72.0-SNAPSHOT",  # CURRENT_GRPC_VERSION
+    version = "1.72.1-SNAPSHOT",  # CURRENT_GRPC_VERSION
 )
 
 # GRPC_DEPS_START
diff --git a/README.md b/README.md
index 756519d0ad0..d1b4d516f74 100644
--- a/README.md
+++ b/README.md
@@ -44,8 +44,8 @@ For a guided tour, take a look at the [quick start
 guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC
 basics](https://grpc.io/docs/languages/java/basics).
 
-The [examples](https://github.com/grpc/grpc-java/tree/v1.71.0/examples) and the
-[Android example](https://github.com/grpc/grpc-java/tree/v1.71.0/examples/android)
+The [examples](https://github.com/grpc/grpc-java/tree/v1.72.0/examples) and the
+[Android example](https://github.com/grpc/grpc-java/tree/v1.72.0/examples/android)
 are standalone projects that showcase the usage of gRPC.
 
 Download
@@ -56,18 +56,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
 <dependency>
   <groupId>io.grpc</groupId>
   <artifactId>grpc-netty-shaded</artifactId>
-  <version>1.71.0</version>
+  <version>1.72.0</version>
   <scope>runtime</scope>
 </dependency>
 <dependency>
   <groupId>io.grpc</groupId>
   <artifactId>grpc-protobuf</artifactId>
-  <version>1.71.0</version>
+  <version>1.72.0</version>
 </dependency>
 <dependency>
   <groupId>io.grpc</groupId>
   <artifactId>grpc-stub</artifactId>
-  <version>1.71.0</version>
+  <version>1.72.0</version>
 </dependency>
 <dependency> <!-- necessary for Java 9+ -->
   <groupId>org.apache.tomcat</groupId>
@@ -79,18 +79,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
 
 Or for Gradle with non-Android, add to your dependencies:
 ```gradle
-runtimeOnly 'io.grpc:grpc-netty-shaded:1.71.0'
-implementation 'io.grpc:grpc-protobuf:1.71.0'
-implementation 'io.grpc:grpc-stub:1.71.0'
+runtimeOnly 'io.grpc:grpc-netty-shaded:1.72.0'
+implementation 'io.grpc:grpc-protobuf:1.72.0'
+implementation 'io.grpc:grpc-stub:1.72.0'
 compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
 ```
 
 For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and
 `grpc-protobuf-lite` instead of `grpc-protobuf`:
 ```gradle
-implementation 'io.grpc:grpc-okhttp:1.71.0'
-implementation 'io.grpc:grpc-protobuf-lite:1.71.0'
-implementation 'io.grpc:grpc-stub:1.71.0'
+implementation 'io.grpc:grpc-okhttp:1.72.0'
+implementation 'io.grpc:grpc-protobuf-lite:1.72.0'
+implementation 'io.grpc:grpc-stub:1.72.0'
 compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
 ```
 
@@ -99,7 +99,7 @@ For [Bazel](https://bazel.build), you can either
 (with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below).
 
 [the JARs]:
-https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.71.0
+https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.72.0
 
 Development snapshots are available in [Sonatypes's snapshot
 repository](https://oss.sonatype.org/content/repositories/snapshots/).
@@ -131,7 +131,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use
       <configuration>
         <protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact>
         <pluginId>grpc-java</pluginId>
-        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.71.0:exe:${os.detected.classifier}</pluginArtifact>
+        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.72.0:exe:${os.detected.classifier}</pluginArtifact>
       </configuration>
       <executions>
         <execution>
@@ -161,7 +161,7 @@ protobuf {
   }
   plugins {
     grpc {
-      artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0'
+      artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0'
     }
   }
   generateProtoTasks {
@@ -194,7 +194,7 @@ protobuf {
   }
   plugins {
     grpc {
-      artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0'
+      artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0'
     }
   }
   generateProtoTasks {
diff --git a/build.gradle b/build.gradle
index 93ce60054bc..e63e03d22d2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,7 +21,7 @@ subprojects {
     apply plugin: "net.ltgt.errorprone"
 
     group = "io.grpc"
-    version = "1.72.0-SNAPSHOT" // CURRENT_GRPC_VERSION
+    version = "1.72.1-SNAPSHOT" // CURRENT_GRPC_VERSION
 
     repositories {
         maven { // The google mirror is less flaky than mavenCentral()
diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt
index 82fe6a81d18..44d4dc93175 100644
--- a/compiler/src/test/golden/TestDeprecatedService.java.txt
+++ b/compiler/src/test/golden/TestDeprecatedService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
  * </pre>
  */
 @javax.annotation.Generated(
-    value = "by gRPC proto compiler (version 1.72.0-SNAPSHOT)",
+    value = "by gRPC proto compiler (version 1.72.1-SNAPSHOT)",
     comments = "Source: grpc/testing/compiler/test.proto")
 @io.grpc.stub.annotations.GrpcGenerated
 @java.lang.Deprecated
diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
index 912bd50da12..085ba3abe46 100644
--- a/compiler/src/test/golden/TestService.java.txt
+++ b/compiler/src/test/golden/TestService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
  * </pre>
  */
 @javax.annotation.Generated(
-    value = "by gRPC proto compiler (version 1.72.0-SNAPSHOT)",
+    value = "by gRPC proto compiler (version 1.72.1-SNAPSHOT)",
     comments = "Source: grpc/testing/compiler/test.proto")
 @io.grpc.stub.annotations.GrpcGenerated
 public final class TestServiceGrpc {
diff --git a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java
index 8ff755af3eb..eccd8fadc8c 100644
--- a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java
+++ b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java
@@ -325,7 +325,11 @@ final void reprocess(@Nullable SubchannelPicker picker) {
       if (!hasPendingStreams()) {
         return;
       }
-      pendingStreams.removeAll(toRemove);
+      // Avoid pendingStreams.removeAll() as it can degrade to calling toRemove.contains() for each
+      // element in pendingStreams.
+      for (PendingStream stream : toRemove) {
+        pendingStreams.remove(stream);
+      }
       // Because delayed transport is long-lived, we take this opportunity to down-size the
       // hashmap.
       if (pendingStreams.isEmpty()) {
diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java
index 937854ac3ff..fef4b638941 100644
--- a/core/src/main/java/io/grpc/internal/GrpcUtil.java
+++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java
@@ -219,7 +219,7 @@ public byte[] parseAsciiString(byte[] serialized) {
 
   public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults();
 
-  public static final String IMPLEMENTATION_VERSION = "1.72.0-SNAPSHOT"; // CURRENT_GRPC_VERSION
+  public static final String IMPLEMENTATION_VERSION = "1.72.1-SNAPSHOT"; // CURRENT_GRPC_VERSION
 
   /**
    * The default timeout in nanos for a keepalive ping request.
diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel
index 4d72ae9c395..3612ec2640c 100644
--- a/examples/MODULE.bazel
+++ b/examples/MODULE.bazel
@@ -1,5 +1,5 @@
 bazel_dep(name = "googleapis", repo_name = "com_google_googleapis", version = "0.0.0-20240326-1c8d509c5")
-bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.0-SNAPSHOT")  # CURRENT_GRPC_VERSION
+bazel_dep(name = "grpc-java", repo_name = "io_grpc_grpc_java", version = "1.72.1-SNAPSHOT")  # CURRENT_GRPC_VERSION
 bazel_dep(name = "grpc-proto", repo_name = "io_grpc_grpc_proto", version = "0.0.0-20240627-ec30f58")
 bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "23.1")
 bazel_dep(name = "rules_jvm_external", version = "6.0")
diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle
index 1f2a17ae6bb..f68e4b52061 100644
--- a/examples/android/clientcache/app/build.gradle
+++ b/examples/android/clientcache/app/build.gradle
@@ -34,7 +34,7 @@ android {
 protobuf {
     protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
     plugins {
-        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
         }
     }
     generateProtoTasks {
@@ -54,12 +54,12 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.0.0'
 
     // You need to build grpc-java to obtain these libraries below.
-    implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
     implementation 'org.apache.tomcat:annotations-api:6.0.53'
 
     testImplementation 'junit:junit:4.13.2'
     testImplementation 'com.google.truth:truth:1.1.5'
-    testImplementation 'io.grpc:grpc-testing:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+    testImplementation 'io.grpc:grpc-testing:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 }
diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle
index 09b994a4954..5ff4fa926b9 100644
--- a/examples/android/helloworld/app/build.gradle
+++ b/examples/android/helloworld/app/build.gradle
@@ -32,7 +32,7 @@ android {
 protobuf {
     protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
     plugins {
-        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
         }
     }
     generateProtoTasks {
@@ -52,8 +52,8 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.0.0'
 
     // You need to build grpc-java to obtain these libraries below.
-    implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
     implementation 'org.apache.tomcat:annotations-api:6.0.53'
 }
diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle
index bdad129845b..1ae9ca28e08 100644
--- a/examples/android/routeguide/app/build.gradle
+++ b/examples/android/routeguide/app/build.gradle
@@ -32,7 +32,7 @@ android {
 protobuf {
     protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
     plugins {
-        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
         }
     }
     generateProtoTasks {
@@ -52,8 +52,8 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.0.0'
 
     // You need to build grpc-java to obtain these libraries below.
-    implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
     implementation 'org.apache.tomcat:annotations-api:6.0.53'
 }
diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle
index f38110a741b..0e4a057675e 100644
--- a/examples/android/strictmode/app/build.gradle
+++ b/examples/android/strictmode/app/build.gradle
@@ -33,7 +33,7 @@ android {
 protobuf {
     protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
     plugins {
-        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
         }
     }
     generateProtoTasks {
@@ -53,8 +53,8 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.0.0'
 
     // You need to build grpc-java to obtain these libraries below.
-    implementation 'io.grpc:grpc-okhttp:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-protobuf-lite:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
-    implementation 'io.grpc:grpc-stub:1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-okhttp:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-protobuf-lite:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
+    implementation 'io.grpc:grpc-stub:1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
     implementation 'org.apache.tomcat:annotations-api:6.0.53'
 }
diff --git a/examples/build.gradle b/examples/build.gradle
index e807d09f407..8dc8cb39716 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 def protocVersion = protobufVersion
 
diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle
index e7142f3fb5a..369f7b212da 100644
--- a/examples/example-alts/build.gradle
+++ b/examples/example-alts/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-debug/build.gradle b/examples/example-debug/build.gradle
index 1d07a7cb8ec..aa13f55d7b7 100644
--- a/examples/example-debug/build.gradle
+++ b/examples/example-debug/build.gradle
@@ -23,7 +23,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-debug/pom.xml b/examples/example-debug/pom.xml
index 00fdecdb6c4..6807df43771 100644
--- a/examples/example-debug/pom.xml
+++ b/examples/example-debug/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-debug</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
     <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/examples/example-dualstack/build.gradle b/examples/example-dualstack/build.gradle
index b73902095a1..b8e8ec5acc4 100644
--- a/examples/example-dualstack/build.gradle
+++ b/examples/example-dualstack/build.gradle
@@ -23,7 +23,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-dualstack/pom.xml b/examples/example-dualstack/pom.xml
index 28539851934..8ed41f27256 100644
--- a/examples/example-dualstack/pom.xml
+++ b/examples/example-dualstack/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-dualstack</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
     <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle
index 0ef0dcaefe2..f4dcf3fb8ce 100644
--- a/examples/example-gauth/build.gradle
+++ b/examples/example-gauth/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 def protocVersion = protobufVersion
 
diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml
index d2a32578550..527916af157 100644
--- a/examples/example-gauth/pom.xml
+++ b/examples/example-gauth/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-gauth</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protobuf.version>3.25.5</protobuf.version>
     <!-- required for jdk9 -->
     <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/examples/example-gcp-csm-observability/build.gradle b/examples/example-gcp-csm-observability/build.gradle
index e16e32e3bc1..c0062d69efd 100644
--- a/examples/example-gcp-csm-observability/build.gradle
+++ b/examples/example-gcp-csm-observability/build.gradle
@@ -22,7 +22,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 def openTelemetryVersion = '1.40.0'
 def openTelemetryPrometheusVersion = '1.40.0-alpha'
diff --git a/examples/example-gcp-observability/build.gradle b/examples/example-gcp-observability/build.gradle
index 1cad10bbb87..85703711527 100644
--- a/examples/example-gcp-observability/build.gradle
+++ b/examples/example-gcp-observability/build.gradle
@@ -22,7 +22,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle
index 86aa42f8ed0..3676c3ea850 100644
--- a/examples/example-hostname/build.gradle
+++ b/examples/example-hostname/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml
index 6993c40a1ac..46644f3ee7c 100644
--- a/examples/example-hostname/pom.xml
+++ b/examples/example-hostname/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-hostname</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
     <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle
index ca12c3f7872..2382365fd82 100644
--- a/examples/example-jwt-auth/build.gradle
+++ b/examples/example-jwt-auth/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 def protocVersion = protobufVersion
 
diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml
index 7e9a915bfbd..a92e1c96dd2 100644
--- a/examples/example-jwt-auth/pom.xml
+++ b/examples/example-jwt-auth/pom.xml
@@ -7,13 +7,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-jwt-auth</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protobuf.version>3.25.5</protobuf.version>
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
diff --git a/examples/example-oauth/build.gradle b/examples/example-oauth/build.gradle
index 6d06f097ccb..d2e1654f0f8 100644
--- a/examples/example-oauth/build.gradle
+++ b/examples/example-oauth/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protobufVersion = '3.25.5'
 def protocVersion = protobufVersion
 
diff --git a/examples/example-oauth/pom.xml b/examples/example-oauth/pom.xml
index a9fea928a34..17514f95116 100644
--- a/examples/example-oauth/pom.xml
+++ b/examples/example-oauth/pom.xml
@@ -7,13 +7,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-oauth</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protobuf.version>3.25.5</protobuf.version>
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
diff --git a/examples/example-opentelemetry/build.gradle b/examples/example-opentelemetry/build.gradle
index f575d24d19b..b4b78461812 100644
--- a/examples/example-opentelemetry/build.gradle
+++ b/examples/example-opentelemetry/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 def openTelemetryVersion = '1.40.0'
 def openTelemetryPrometheusVersion = '1.40.0-alpha'
diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle
index 45235fa1e08..3944e451403 100644
--- a/examples/example-orca/build.gradle
+++ b/examples/example-orca/build.gradle
@@ -16,7 +16,7 @@ java {
     targetCompatibility = JavaVersion.VERSION_1_8
 }
 
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-reflection/build.gradle b/examples/example-reflection/build.gradle
index ad68e891436..9dcbbd6c354 100644
--- a/examples/example-reflection/build.gradle
+++ b/examples/example-reflection/build.gradle
@@ -16,7 +16,7 @@ java {
     targetCompatibility = JavaVersion.VERSION_1_8
 }
 
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle
index 2176df5afc5..da4a8744da1 100644
--- a/examples/example-servlet/build.gradle
+++ b/examples/example-servlet/build.gradle
@@ -15,7 +15,7 @@ java {
     targetCompatibility = JavaVersion.VERSION_1_8
 }
 
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle
index e741bfe1c3f..49f0383b49a 100644
--- a/examples/example-tls/build.gradle
+++ b/examples/example-tls/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml
index de9298cf0e1..93095aa01d9 100644
--- a/examples/example-tls/pom.xml
+++ b/examples/example-tls/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>example-tls</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protoc.version>3.25.5</protoc.version>
     <!-- required for jdk9 -->
     <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle
index c0159dce258..16a85758c9d 100644
--- a/examples/example-xds/build.gradle
+++ b/examples/example-xds/build.gradle
@@ -21,7 +21,7 @@ java {
 
 // Feel free to delete the comment at the next line. It is just for safely
 // updating the version in our release process.
-def grpcVersion = '1.72.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.72.1-SNAPSHOT' // CURRENT_GRPC_VERSION
 def protocVersion = '3.25.5'
 
 dependencies {
diff --git a/examples/pom.xml b/examples/pom.xml
index edc9c4cda14..ac60626c578 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -6,13 +6,13 @@
   <packaging>jar</packaging>
   <!-- Feel free to delete the comment at the end of these lines. It is just
        for safely updating the version in our release process. -->
-  <version>1.72.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
+  <version>1.72.1-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
   <name>examples</name>
   <url>https://github.com/grpc/grpc-java</url>
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <grpc.version>1.72.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
+    <grpc.version>1.72.1-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
     <protobuf.version>3.25.5</protobuf.version>
     <protoc.version>3.25.5</protoc.version>
     <!-- required for JDK 8 -->
diff --git a/stub/src/main/java/io/grpc/stub/ServerCalls.java b/stub/src/main/java/io/grpc/stub/ServerCalls.java
index 7990a5b34c0..9f0063713cc 100644
--- a/stub/src/main/java/io/grpc/stub/ServerCalls.java
+++ b/stub/src/main/java/io/grpc/stub/ServerCalls.java
@@ -382,9 +382,10 @@ public void onNext(RespT response) {
 
     @Override
     public void onError(Throwable t) {
-      Metadata metadata = Status.trailersFromThrowable(t);
-      if (metadata == null) {
-        metadata = new Metadata();
+      Metadata metadata = new Metadata();
+      Metadata trailers = Status.trailersFromThrowable(t);
+      if (trailers != null) {
+        metadata.merge(trailers);
       }
       call.close(Status.fromThrowable(t), metadata);
       aborted = true;
diff --git a/stub/src/main/java/io/grpc/stub/StreamObservers.java b/stub/src/main/java/io/grpc/stub/StreamObservers.java
index 2cc53ea0aa2..a421d3eca2f 100644
--- a/stub/src/main/java/io/grpc/stub/StreamObservers.java
+++ b/stub/src/main/java/io/grpc/stub/StreamObservers.java
@@ -23,12 +23,21 @@
 /**
  * Utility functions for working with {@link StreamObserver} and it's common subclasses like
  * {@link CallStreamObserver}.
- *
- * @deprecated Of questionable utility and generally not used.
  */
-@Deprecated
-@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694")
 public final class StreamObservers {
+  // Prevent instantiation
+  private StreamObservers() { }
+
+  /**
+   * Utility method to call {@link StreamObserver#onNext(Object)} and
+   * {@link StreamObserver#onCompleted()} on the specified responseObserver.
+   */
+  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10957")
+  public static <T> void nextAndComplete(StreamObserver<T> responseObserver, T response) {
+    responseObserver.onNext(response);
+    responseObserver.onCompleted();
+  }
+
   /**
    * Copy the values of an {@link Iterator} to the target {@link CallStreamObserver} while properly
    * accounting for outbound flow-control.  After calling this method, {@code target} should no
@@ -40,7 +49,10 @@ public final class StreamObservers {
    *
    * @param source of values expressed as an {@link Iterator}.
    * @param target {@link CallStreamObserver} which accepts values from the source.
+   * @deprecated Of questionable utility and generally not used.
    */
+  @Deprecated
+  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694")
   public static <V> void copyWithFlowControl(final Iterator<V> source,
       final CallStreamObserver<V> target) {
     Preconditions.checkNotNull(source, "source");
@@ -80,7 +92,10 @@ public void run() {
    *
    * @param source of values expressed as an {@link Iterable}.
    * @param target {@link CallStreamObserver} which accepts values from the source.
+   * @deprecated Of questionable utility and generally not used.
    */
+  @Deprecated
+  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4694")
   public static <V> void copyWithFlowControl(final Iterable<V> source,
       CallStreamObserver<V> target) {
     Preconditions.checkNotNull(source, "source");
diff --git a/stub/src/test/java/io/grpc/stub/ServerCallsTest.java b/stub/src/test/java/io/grpc/stub/ServerCallsTest.java
index 1e51ac10110..6f458facc5e 100644
--- a/stub/src/test/java/io/grpc/stub/ServerCallsTest.java
+++ b/stub/src/test/java/io/grpc/stub/ServerCallsTest.java
@@ -555,6 +555,35 @@ public void invoke(Integer req, StreamObserver<Integer> responseObserver) {
     listener.onHalfClose();
   }
 
+  @Test
+  public void clientSendsOne_serverOnErrorWithTrailers_serverStreaming() {
+    Metadata trailers = new Metadata();
+    Metadata.Key<String> key = Metadata.Key.of("trailers-test-key1",
+            Metadata.ASCII_STRING_MARSHALLER);
+    trailers.put(key, "trailers-test-value1");
+
+    ServerCallRecorder serverCall = new ServerCallRecorder(SERVER_STREAMING_METHOD);
+    ServerCallHandler<Integer, Integer> callHandler = ServerCalls.asyncServerStreamingCall(
+        new ServerCalls.ServerStreamingMethod<Integer, Integer>() {
+          @Override
+          public void invoke(Integer req, StreamObserver<Integer> responseObserver) {
+            responseObserver.onError(
+                    Status.fromCode(Status.Code.INTERNAL)
+                            .asRuntimeException(trailers)
+            );
+          }
+        });
+    ServerCall.Listener<Integer> listener = callHandler.startCall(serverCall, new Metadata());
+    serverCall.isReady = true;
+    serverCall.isCancelled = false;
+    listener.onReady();
+    listener.onMessage(1);
+    listener.onHalfClose();
+    // verify trailers key is set
+    assertTrue(serverCall.trailers.containsKey(key));
+    assertTrue(serverCall.status.equals(Status.INTERNAL));
+  }
+
   @Test
   public void inprocessTransportManualFlow() throws Exception {
     final Semaphore semaphore = new Semaphore(1);
@@ -652,6 +681,7 @@ private static class ServerCallRecorder extends ServerCall<Integer, Integer> {
     private boolean isCancelled;
     private boolean isReady;
     private int onReadyThreshold;
+    private Metadata trailers;
 
     public ServerCallRecorder(MethodDescriptor<Integer, Integer> methodDescriptor) {
       this.methodDescriptor = methodDescriptor;
@@ -674,6 +704,7 @@ public void sendMessage(Integer message) {
     @Override
     public void close(Status status, Metadata trailers) {
       this.status = status;
+      this.trailers = trailers;
     }
 
     @Override
diff --git a/stub/src/test/java/io/grpc/stub/StreamObserversTest.java b/stub/src/test/java/io/grpc/stub/StreamObserversTest.java
new file mode 100644
index 00000000000..86a1aba2e76
--- /dev/null
+++ b/stub/src/test/java/io/grpc/stub/StreamObserversTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2025 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.stub;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+public class StreamObserversTest {
+
+  @Test
+  public void nextAndComplete() {
+    @SuppressWarnings("unchecked")
+    StreamObserver<String> observer = Mockito.mock(StreamObserver.class);
+    InOrder inOrder = Mockito.inOrder(observer);
+    StreamObservers.nextAndComplete(observer, "TEST");
+    inOrder.verify(observer).onNext("TEST");
+    inOrder.verify(observer).onCompleted();
+    inOrder.verifyNoMoreInteractions();
+  }
+}
diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
index c92f592ebc8..0fb7cf15909 100644
--- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
+++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java
@@ -33,6 +33,7 @@
 import io.grpc.NameResolver;
 import io.grpc.NameResolver.ResolutionResult;
 import io.grpc.Status;
+import io.grpc.StatusOr;
 import io.grpc.SynchronizationContext;
 import io.grpc.SynchronizationContext.ScheduledHandle;
 import io.grpc.internal.BackoffPolicy;
@@ -657,79 +658,84 @@ private class NameResolverListener extends NameResolver.Listener2 {
 
         @Override
         public void onResult(final ResolutionResult resolutionResult) {
-          class NameResolved implements Runnable {
-            @Override
-            public void run() {
-              if (shutdown) {
-                return;
-              }
-              backoffPolicy = null;  // reset backoff sequence if succeeded
-              // Arbitrary priority notation for all DNS-resolved endpoints.
-              String priorityName = priorityName(name, 0);  // value doesn't matter
-              List<EquivalentAddressGroup> addresses = new ArrayList<>();
-              for (EquivalentAddressGroup eag : resolutionResult.getAddresses()) {
-                // No weight attribute is attached, all endpoint-level LB policy should be able
-                // to handle such it.
-                String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY);
-                Attributes attr = eag.getAttributes().toBuilder()
-                    .set(XdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY)
-                    .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName)
-                    .set(XdsAttributes.ATTR_ADDRESS_NAME, dnsHostName)
-                    .build();
-                eag = new EquivalentAddressGroup(eag.getAddresses(), attr);
-                eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName));
-                addresses.add(eag);
-              }
-              PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig(
-                  name, lrsServerInfo, maxConcurrentRequests, tlsContext, filterMetadata,
-                  lbRegistry, Collections.<DropOverload>emptyList());
-              status = Status.OK;
-              resolved = true;
-              result = new ClusterResolutionResult(addresses, priorityName, priorityChildConfig);
-              handleEndpointResourceUpdate();
+          syncContext.execute(() -> onResult2(resolutionResult));
+        }
+
+        @Override
+        public Status onResult2(final ResolutionResult resolutionResult) {
+          if (shutdown) {
+            return Status.OK;
+          }
+          // Arbitrary priority notation for all DNS-resolved endpoints.
+          String priorityName = priorityName(name, 0);  // value doesn't matter
+          List<EquivalentAddressGroup> addresses = new ArrayList<>();
+          StatusOr<List<EquivalentAddressGroup>> addressesOrError =
+                  resolutionResult.getAddressesOrError();
+          if (addressesOrError.hasValue()) {
+            backoffPolicy = null;  // reset backoff sequence if succeeded
+            for (EquivalentAddressGroup eag : resolutionResult.getAddresses()) {
+              // No weight attribute is attached, all endpoint-level LB policy should be able
+              // to handle such it.
+              String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY);
+              Attributes attr = eag.getAttributes().toBuilder()
+                      .set(XdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY)
+                      .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName)
+                      .set(XdsAttributes.ATTR_ADDRESS_NAME, dnsHostName)
+                      .build();
+              eag = new EquivalentAddressGroup(eag.getAddresses(), attr);
+              eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName));
+              addresses.add(eag);
             }
+            PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig(
+                    name, lrsServerInfo, maxConcurrentRequests, tlsContext, filterMetadata,
+                    lbRegistry, Collections.<DropOverload>emptyList());
+            status = Status.OK;
+            resolved = true;
+            result = new ClusterResolutionResult(addresses, priorityName, priorityChildConfig);
+            handleEndpointResourceUpdate();
+            return Status.OK;
+          } else {
+            handleErrorInSyncContext(addressesOrError.getStatus());
+            return addressesOrError.getStatus();
           }
-
-          syncContext.execute(new NameResolved());
         }
 
         @Override
         public void onError(final Status error) {
-          syncContext.execute(new Runnable() {
-            @Override
-            public void run() {
-              if (shutdown) {
-                return;
-              }
-              status = error;
-              // NameResolver.Listener API cannot distinguish between address-not-found and
-              // transient errors. If the error occurs in the first resolution, treat it as
-              // address not found. Otherwise, either there is previously resolved addresses
-              // previously encountered error, propagate the error to downstream/upstream and
-              // let downstream/upstream handle it.
-              if (!resolved) {
-                resolved = true;
-                handleEndpointResourceUpdate();
-              } else {
-                handleEndpointResolutionError();
-              }
-              if (scheduledRefresh != null && scheduledRefresh.isPending()) {
-                return;
-              }
-              if (backoffPolicy == null) {
-                backoffPolicy = backoffPolicyProvider.get();
-              }
-              long delayNanos = backoffPolicy.nextBackoffNanos();
-              logger.log(XdsLogLevel.DEBUG,
+          syncContext.execute(() -> handleErrorInSyncContext(error));
+        }
+
+        private void handleErrorInSyncContext(final Status error) {
+          if (shutdown) {
+            return;
+          }
+          status = error;
+          // NameResolver.Listener API cannot distinguish between address-not-found and
+          // transient errors. If the error occurs in the first resolution, treat it as
+          // address not found. Otherwise, either there is previously resolved addresses
+          // previously encountered error, propagate the error to downstream/upstream and
+          // let downstream/upstream handle it.
+          if (!resolved) {
+            resolved = true;
+            handleEndpointResourceUpdate();
+          } else {
+            handleEndpointResolutionError();
+          }
+          if (scheduledRefresh != null && scheduledRefresh.isPending()) {
+            return;
+          }
+          if (backoffPolicy == null) {
+            backoffPolicy = backoffPolicyProvider.get();
+          }
+          long delayNanos = backoffPolicy.nextBackoffNanos();
+          logger.log(XdsLogLevel.DEBUG,
                   "Logical DNS resolver for cluster {0} encountered name resolution "
-                      + "error: {1}, scheduling DNS resolution backoff for {2} ns",
+                          + "error: {1}, scheduling DNS resolution backoff for {2} ns",
                   name, error, delayNanos);
-              scheduledRefresh =
+          scheduledRefresh =
                   syncContext.schedule(
-                      new DelayedNameResolverRefresh(), delayNanos, TimeUnit.NANOSECONDS,
-                      timeService);
-            }
-          });
+                          new DelayedNameResolverRefresh(), delayNanos, TimeUnit.NANOSECONDS,
+                          timeService);
         }
       }
     }
diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java
index d0176d7aa38..d701f281c01 100644
--- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java
+++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java
@@ -200,6 +200,7 @@ public XdsClient returnObject(Object object) {
   private ArgumentCaptor<SubchannelPicker> pickerCaptor;
   private int xdsClientRefs;
   private ClusterResolverLoadBalancer loadBalancer;
+  private NameResolverProvider fakeNameResolverProvider;
 
   @Before
   public void setUp() throws URISyntaxException {
@@ -216,7 +217,8 @@ public void setUp() throws URISyntaxException {
         .setServiceConfigParser(mock(ServiceConfigParser.class))
         .setChannelLogger(mock(ChannelLogger.class))
         .build();
-    nsRegistry.register(new FakeNameResolverProvider());
+    fakeNameResolverProvider = new FakeNameResolverProvider(false);
+    nsRegistry.register(fakeNameResolverProvider);
     when(helper.getNameResolverRegistry()).thenReturn(nsRegistry);
     when(helper.getNameResolverArgs()).thenReturn(args);
     when(helper.getSynchronizationContext()).thenReturn(syncContext);
@@ -826,6 +828,17 @@ public void handleEdsResource_noHealthyEndpoint() {
 
   @Test
   public void onlyLogicalDnsCluster_endpointsResolved() {
+    do_onlyLogicalDnsCluster_endpointsResolved();
+  }
+
+  @Test
+  public void oldListenerCallback_onlyLogicalDnsCluster_endpointsResolved() {
+    nsRegistry.deregister(fakeNameResolverProvider);
+    nsRegistry.register(new FakeNameResolverProvider(true));
+    do_onlyLogicalDnsCluster_endpointsResolved();
+  }
+
+  void do_onlyLogicalDnsCluster_endpointsResolved() {
     ClusterResolverConfig config = new ClusterResolverConfig(
         Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false);
     deliverLbConfig(config);
@@ -854,7 +867,6 @@ public void onlyLogicalDnsCluster_endpointsResolved() {
         .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME);
     assertThat(childBalancer.addresses.get(1).getAttributes()
         .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME);
-
   }
 
   @Test
@@ -874,37 +886,48 @@ public void onlyLogicalDnsCluster_handleRefreshNameResolution() {
   }
 
   @Test
-  public void onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() {
+  public void resolutionError_backoffAndRefresh() {
+    do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh();
+  }
+
+  @Test
+  public void oldListenerCallback_resolutionError_backoffAndRefresh() {
+    nsRegistry.deregister(fakeNameResolverProvider);
+    nsRegistry.register(new FakeNameResolverProvider(true));
+    do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh();
+  }
+
+  void do_onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() {
     InOrder inOrder = Mockito.inOrder(helper, backoffPolicyProvider,
-        backoffPolicy1, backoffPolicy2);
+            backoffPolicy1, backoffPolicy2);
     ClusterResolverConfig config = new ClusterResolverConfig(
-        Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false);
+            Collections.singletonList(logicalDnsDiscoveryMechanism), roundRobin, false);
     deliverLbConfig(config);
     FakeNameResolver resolver = assertResolverCreated("/" + DNS_HOST_NAME);
     assertThat(childBalancers).isEmpty();
     Status error = Status.UNAVAILABLE.withDescription("cannot reach DNS server");
     resolver.deliverError(error);
     inOrder.verify(helper).updateBalancingState(
-        eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture());
+            eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture());
     assertPicker(pickerCaptor.getValue(), error, null);
     assertThat(resolver.refreshCount).isEqualTo(0);
     inOrder.verify(backoffPolicyProvider).get();
     inOrder.verify(backoffPolicy1).nextBackoffNanos();
     assertThat(fakeClock.getPendingTasks()).hasSize(1);
     assertThat(Iterables.getOnlyElement(fakeClock.getPendingTasks()).getDelay(TimeUnit.SECONDS))
-        .isEqualTo(1L);
+            .isEqualTo(1L);
     fakeClock.forwardTime(1L, TimeUnit.SECONDS);
     assertThat(resolver.refreshCount).isEqualTo(1);
 
     error = Status.UNKNOWN.withDescription("I am lost");
     resolver.deliverError(error);
     inOrder.verify(helper).updateBalancingState(
-        eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture());
+            eq(ConnectivityState.TRANSIENT_FAILURE), pickerCaptor.capture());
     inOrder.verify(backoffPolicy1).nextBackoffNanos();
     assertPicker(pickerCaptor.getValue(), error, null);
     assertThat(fakeClock.getPendingTasks()).hasSize(1);
     assertThat(Iterables.getOnlyElement(fakeClock.getPendingTasks()).getDelay(TimeUnit.SECONDS))
-        .isEqualTo(10L);
+            .isEqualTo(10L);
     fakeClock.forwardTime(10L, TimeUnit.SECONDS);
     assertThat(resolver.refreshCount).isEqualTo(2);
 
@@ -914,7 +937,7 @@ public void onlyLogicalDnsCluster_resolutionError_backoffAndRefresh() {
     resolver.deliverEndpointAddresses(Arrays.asList(endpoint1, endpoint2));
     assertThat(childBalancers).hasSize(1);
     assertAddressesEqual(Arrays.asList(endpoint1, endpoint2),
-        Iterables.getOnlyElement(childBalancers).addresses);
+            Iterables.getOnlyElement(childBalancers).addresses);
 
     assertThat(fakeClock.getPendingTasks()).isEmpty();
     inOrder.verifyNoMoreInteractions();
@@ -1319,10 +1342,18 @@ void deliverError(Status error) {
   }
 
   private class FakeNameResolverProvider extends NameResolverProvider {
+    private final boolean useOldListenerCallback;
+
+    private FakeNameResolverProvider(boolean useOldListenerCallback) {
+      this.useOldListenerCallback = useOldListenerCallback;
+    }
+
     @Override
     public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
       assertThat(targetUri.getScheme()).isEqualTo("dns");
-      FakeNameResolver resolver = new FakeNameResolver(targetUri);
+      FakeNameResolver resolver = useOldListenerCallback
+              ? new FakeNameResolverUsingOldListenerCallback(targetUri)
+              : new FakeNameResolver(targetUri);
       resolvers.add(resolver);
       return resolver;
     }
@@ -1343,9 +1374,10 @@ protected int priority() {
     }
   }
 
+
   private class FakeNameResolver extends NameResolver {
     private final URI targetUri;
-    private Listener2 listener;
+    protected Listener2 listener;
     private int refreshCount;
 
     private FakeNameResolver(URI targetUri) {
@@ -1372,12 +1404,33 @@ public void shutdown() {
       resolvers.remove(this);
     }
 
-    private void deliverEndpointAddresses(List<EquivalentAddressGroup> addresses) {
+    protected void deliverEndpointAddresses(List<EquivalentAddressGroup> addresses) {
+      syncContext.execute(() -> {
+        Status ret = listener.onResult2(ResolutionResult.newBuilder()
+                .setAddressesOrError(StatusOr.fromValue(addresses)).build());
+        assertThat(ret.getCode()).isEqualTo(Status.Code.OK);
+      });
+    }
+
+    protected void deliverError(Status error) {
+      syncContext.execute(() -> listener.onResult2(ResolutionResult.newBuilder()
+                      .setAddressesOrError(StatusOr.fromStatus(error)).build()));
+    }
+  }
+
+  private class FakeNameResolverUsingOldListenerCallback extends FakeNameResolver {
+    private FakeNameResolverUsingOldListenerCallback(URI targetUri) {
+      super(targetUri);
+    }
+
+    @Override
+    protected void deliverEndpointAddresses(List<EquivalentAddressGroup> addresses) {
       listener.onResult(ResolutionResult.newBuilder()
-          .setAddressesOrError(StatusOr.fromValue(addresses)).build());
+              .setAddressesOrError(StatusOr.fromValue(addresses)).build());
     }
 
-    private void deliverError(Status error) {
+    @Override
+    protected void deliverError(Status error) {
       listener.onError(error);
     }
   }