This is an automated email from the ASF dual-hosted git repository.

hvanhovell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 3298e685a964 [SPARK-55373][CONNECT] Improve noHandlerFoundForExtension 
error message
3298e685a964 is described below

commit 3298e685a9641c3e137917f75f58bc0bcfdfe32e
Author: Alex Khakhlyuk <[email protected]>
AuthorDate: Thu Feb 5 10:45:46 2026 -0400

    [SPARK-55373][CONNECT] Improve noHandlerFoundForExtension error message
    
    ### What changes were proposed in this pull request?
    
    Spark Connect Planner supports extension fields for Relation, Command, 
Expression protos. Extensions are processed through handlers. If a handler is 
not available for a given extension type, the planner will throw this error:
    ```
    org.apache.spark.sql.connect.common.InvalidPlanInput: [INTERNAL_ERROR] No 
handler found for extension SQLSTATE: XX000
    ```
    This error is not informative enough when debugging. I propose adding 
extension proto type url to the error message which will make it clear which 
extension is missing
    ```
    org.apache.spark.sql.connect.common.InvalidPlanInput: [INTERNAL_ERROR] No 
handler found for extension type: 
type.googleapis.com/google.protobuf.StringValue SQLSTATE: XX000
    ```
    
    ### Why are the changes needed?
    
    Improve debuggability of the `noHandlerFoundForExtension` exception.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes, `noHandlerFoundForExtension` will now contain the protobuf type url of 
the missing unsupported extension. E.g. before:
    ```
    org.apache.spark.sql.connect.common.InvalidPlanInput: [INTERNAL_ERROR] No 
handler found for extension SQLSTATE: XX000
    ```
    After:
    ```
    org.apache.spark.sql.connect.common.InvalidPlanInput: [INTERNAL_ERROR] No 
handler found for extension type: 
type.googleapis.com/google.protobuf.StringValue SQLSTATE: XX000
    ```
    
    ### How was this patch tested?
    
    New unit test
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    No
    
    Closes #54160 from khakhlyuk/improve-no-handler-found-for-extension.
    
    Authored-by: Alex Khakhlyuk <[email protected]>
    Signed-off-by: Herman van Hövell <[email protected]>
---
 .../sql/connect/planner/InvalidInputErrors.scala    |  5 +++--
 .../sql/connect/planner/SparkConnectPlanner.scala   |  6 +++---
 .../connect/planner/SparkConnectPlannerSuite.scala  | 21 ++++++++++++++++++++-
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala
 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala
index eb4df9673e59..81c001ed839f 100644
--- 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala
+++ 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala
@@ -30,8 +30,9 @@ import org.apache.spark.sql.types.DataType
 
 object InvalidInputErrors {
 
-  def noHandlerFoundForExtension(): InvalidPlanInput =
-    InvalidPlanInput("No handler found for extension")
+  def noHandlerFoundForExtension(extensionTypeUrl: String): InvalidPlanInput = 
{
+    InvalidPlanInput(s"No handler found for extension type: $extensionTypeUrl")
+  }
 
   def invalidSQLWithReferences(query: proto.WithRelations): InvalidPlanInput =
     InvalidPlanInput(s"$query is not a valid relation for SQL with references")
diff --git 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala
 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala
index d47409d7e681..611e19b01b20 100644
--- 
a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala
+++ 
b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala
@@ -264,7 +264,7 @@ class SparkConnectPlanner(
       .map(p => p.transform(extension.toByteArray, this))
       // Find the first non-empty transformation or throw.
       .find(_.isPresent)
-      .getOrElse(throw InvalidInputErrors.noHandlerFoundForExtension())
+      .getOrElse(throw 
InvalidInputErrors.noHandlerFoundForExtension(extension.getTypeUrl))
       .get()
   }
 
@@ -1948,7 +1948,7 @@ class SparkConnectPlanner(
       .map(p => p.transform(extension.toByteArray, this))
       // Find the first non-empty transformation or throw.
       .find(_.isPresent)
-      .getOrElse(throw InvalidInputErrors.noHandlerFoundForExtension())
+      .getOrElse(throw 
InvalidInputErrors.noHandlerFoundForExtension(extension.getTypeUrl))
       .get
   }
 
@@ -3230,7 +3230,7 @@ class SparkConnectPlanner(
       .map(p => p.process(extension.toByteArray, this))
       // Find the first non-empty transformation or throw.
       .find(_ == true)
-      .getOrElse(throw InvalidInputErrors.noHandlerFoundForExtension())
+      .getOrElse(throw 
InvalidInputErrors.noHandlerFoundForExtension(extension.getTypeUrl))
     executeHolder.eventsManager.postFinished()
   }
 
diff --git 
a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/planner/SparkConnectPlannerSuite.scala
 
b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/planner/SparkConnectPlannerSuite.scala
index 66ff45b553c7..89ccaea93a04 100644
--- 
a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/planner/SparkConnectPlannerSuite.scala
+++ 
b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/planner/SparkConnectPlannerSuite.scala
@@ -19,7 +19,7 @@ package org.apache.spark.sql.connect.planner
 
 import scala.jdk.CollectionConverters._
 
-import com.google.protobuf.ByteString
+import com.google.protobuf.{Any, ByteString, StringValue}
 
 import org.apache.spark.SparkFunSuite
 import org.apache.spark.connect.proto
@@ -1069,4 +1069,23 @@ class SparkConnectPlannerSuite extends SparkFunSuite 
with SparkConnectPlanTest {
         "23:59:59.999999999",
         "23:59:59.999999999").toString)
   }
+
+  test("No handler found for extension shows extension type URL - Relation 
extension") {
+    val extension = StringValue
+      .newBuilder()
+      .setValue("unknown-relation")
+      .build()
+    val relation = proto.Relation
+      .newBuilder()
+      .setExtension(Any.pack(extension))
+      .build()
+
+    val intercepted = intercept[InvalidPlanInput] {
+      transform(relation)
+    }
+
+    assert(
+      intercepted.getMessage.contains("No handler found for extension type: " +
+        "type.googleapis.com/google.protobuf.StringValue"))
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to