You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ya...@apache.org on 2026/07/27 15:37:50 UTC

(spark) branch branch-4.x updated: [SPARK-58363][SQL] Assign a name to the error condition _LEGACY_ERROR_TEMP_2214-2219

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

LuciferYang pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.x by this push:
     new 79d0b1e8c9a2 [SPARK-58363][SQL] Assign a name to the error condition _LEGACY_ERROR_TEMP_2214-2219
79d0b1e8c9a2 is described below

commit 79d0b1e8c9a28057837eb9380b39f7fc1efaf4f7
Author: YangJie <ya...@baidu.com>
AuthorDate: Mon Jul 27 23:36:57 2026 +0800

    [SPARK-58363][SQL] Assign a name to the error condition _LEGACY_ERROR_TEMP_2214-2219
    
    ### What changes were proposed in this pull request?
    
    The catalog-plugin loading failures in `Catalogs.load` were reported with six placeholder error conditions `_LEGACY_ERROR_TEMP_2214` through `_LEGACY_ERROR_TEMP_2219`, none of which carried a SQLSTATE.
    
    Group the six into a single umbrella error condition `CANNOT_LOAD_CATALOG` (SQLSTATE `46103`), with one subclass per failure mode in the `Catalogs.load` try/catch:
    
    - `NOT_A_CATALOG_PLUGIN` — the class does not implement `CatalogPlugin`
    - `PLUGIN_CLASS_NOT_FOUND` — `ClassNotFoundException`
    - `CONSTRUCTOR_NOT_FOUND` — `NoSuchMethodException`
    - `CONSTRUCTOR_NOT_ACCESSIBLE` — `IllegalAccessException`
    - `ABSTRACT_CLASS` — `InstantiationException`
    - `CONSTRUCTOR_FAILURE` — `InvocationTargetException`
    
    This also drops a stray trailing `)` in the legacy `_2216`/`_2217` messages.
    
    ### Why are the changes needed?
    
    The error-conditions README disallows new `_LEGACY_ERROR_TEMP_*` entries and asks existing ones to be resolved. This resolves six of them. SQLSTATE `46103` ("Java Error") is consistent with the sibling `CANNOT_LOAD_FUNCTION_CLASS`; the failures are triggered by a user-supplied `spark.sql.catalog.<name>` plugin class, so they are user-actionable rather than system errors.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. The `_LEGACY_ERROR_TEMP_*` names are not part of the public API. Message text is preserved (except the stray `)` typo removal), now rendered under the umbrella prefix.
    
    ### How was this patch tested?
    
    Updated the existing `checkError`/condition assertions in `CatalogLoadingSuite` and `SupportsCatalogOptionsSuite`, and added tests for the previously-uncovered `CONSTRUCTOR_NOT_FOUND` and `ABSTRACT_CLASS` subclasses. `build/sbt "catalyst/testOnly *CatalogLoadingSuite" "core/testOnly org.apache.spark.SparkThrowableSuite"` passes.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8)
    
    Closes #57556 from LuciferYang/assign-name-legacy-2214-2219.
    
    Authored-by: YangJie <ya...@baidu.com>
    Signed-off-by: yangjie01 <ya...@baidu.com>
    (cherry picked from commit 54d5f5125972fc0f358a9716c30ab8e82bd53b40)
    Signed-off-by: yangjie01 <ya...@baidu.com>
---
 .../src/main/resources/error/error-conditions.json | 68 ++++++++++++----------
 .../spark/sql/errors/QueryExecutionErrors.scala    | 12 ++--
 .../sql/connector/catalog/CatalogLoadingSuite.java | 63 ++++++++++++++++++--
 .../connector/SupportsCatalogOptionsSuite.scala    |  2 +-
 4 files changed, 102 insertions(+), 43 deletions(-)

diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json
index 26a5749f2931..05aec78e0919 100644
--- a/common/utils/src/main/resources/error/error-conditions.json
+++ b/common/utils/src/main/resources/error/error-conditions.json
@@ -557,6 +557,44 @@
     ],
     "sqlState" : "0A000"
   },
+  "CANNOT_LOAD_CATALOG" : {
+    "message" : [
+      "Cannot load catalog '<name>' with the plugin class '<pluginClassName>':"
+    ],
+    "subClass" : {
+      "ABSTRACT_CLASS" : {
+        "message" : [
+          "the class is abstract and cannot be instantiated."
+        ]
+      },
+      "CONSTRUCTOR_FAILURE" : {
+        "message" : [
+          "the constructor threw an exception during instantiation."
+        ]
+      },
+      "CONSTRUCTOR_NOT_ACCESSIBLE" : {
+        "message" : [
+          "failed to call the public no-arg constructor."
+        ]
+      },
+      "CONSTRUCTOR_NOT_FOUND" : {
+        "message" : [
+          "failed to find the public no-arg constructor."
+        ]
+      },
+      "NOT_A_CATALOG_PLUGIN" : {
+        "message" : [
+          "the class does not implement CatalogPlugin."
+        ]
+      },
+      "PLUGIN_CLASS_NOT_FOUND" : {
+        "message" : [
+          "cannot find the plugin class."
+        ]
+      }
+    },
+    "sqlState" : "46103"
+  },
   "CANNOT_LOAD_CHECKPOINT_FILE_MANAGER" : {
     "message" : [
       "Error loading streaming checkpoint file manager for path=<path>."
@@ -10956,36 +10994,6 @@
       "Invalid catalog name: <name>."
     ]
   },
-  "_LEGACY_ERROR_TEMP_2214" : {
-    "message" : [
-      "Plugin class for catalog '<name>' does not implement CatalogPlugin: <pluginClassName>."
-    ]
-  },
-  "_LEGACY_ERROR_TEMP_2215" : {
-    "message" : [
-      "Cannot find catalog plugin class for catalog '<name>': <pluginClassName>."
-    ]
-  },
-  "_LEGACY_ERROR_TEMP_2216" : {
-    "message" : [
-      "Failed to find public no-arg constructor for catalog '<name>': <pluginClassName>)."
-    ]
-  },
-  "_LEGACY_ERROR_TEMP_2217" : {
-    "message" : [
-      "Failed to call public no-arg constructor for catalog '<name>': <pluginClassName>)."
-    ]
-  },
-  "_LEGACY_ERROR_TEMP_2218" : {
-    "message" : [
-      "Cannot instantiate abstract catalog plugin class for catalog '<name>': <pluginClassName>."
-    ]
-  },
-  "_LEGACY_ERROR_TEMP_2219" : {
-    "message" : [
-      "Failed during instantiating constructor for catalog '<name>': <pluginClassName>."
-    ]
-  },
   "_LEGACY_ERROR_TEMP_2220" : {
     "message" : [
       ""
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
index 80feddecff30..c6bd11ae7167 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
@@ -1908,7 +1908,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
 
   def catalogPluginClassNotImplementedError(name: String, pluginClassName: String): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2214",
+      errorClass = "CANNOT_LOAD_CATALOG.NOT_A_CATALOG_PLUGIN",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
@@ -1920,7 +1920,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
       pluginClassName: String,
       e: Exception): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2215",
+      errorClass = "CANNOT_LOAD_CATALOG.PLUGIN_CLASS_NOT_FOUND",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
@@ -1932,7 +1932,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
       pluginClassName: String,
       e: Exception): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2216",
+      errorClass = "CANNOT_LOAD_CATALOG.CONSTRUCTOR_NOT_FOUND",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
@@ -1944,7 +1944,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
       pluginClassName: String,
       e: Exception): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2217",
+      errorClass = "CANNOT_LOAD_CATALOG.CONSTRUCTOR_NOT_ACCESSIBLE",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
@@ -1956,7 +1956,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
       pluginClassName: String,
       e: Exception): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2218",
+      errorClass = "CANNOT_LOAD_CATALOG.ABSTRACT_CLASS",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
@@ -1968,7 +1968,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
       pluginClassName: String,
       e: Exception): Throwable = {
     new SparkException(
-      errorClass = "_LEGACY_ERROR_TEMP_2219",
+      errorClass = "CANNOT_LOAD_CATALOG.CONSTRUCTOR_FAILURE",
       messageParameters = Map(
         "name" -> name,
         "pluginClassName" -> pluginClassName),
diff --git a/sql/catalyst/src/test/java/org/apache/spark/sql/connector/catalog/CatalogLoadingSuite.java b/sql/catalyst/src/test/java/org/apache/spark/sql/connector/catalog/CatalogLoadingSuite.java
index c7e8d7b0f7f3..655cb55852a7 100644
--- a/sql/catalyst/src/test/java/org/apache/spark/sql/connector/catalog/CatalogLoadingSuite.java
+++ b/sql/catalyst/src/test/java/org/apache/spark/sql/connector/catalog/CatalogLoadingSuite.java
@@ -97,7 +97,7 @@ public class CatalogLoadingSuite {
     SparkException exc = Assertions.assertThrows(SparkException.class,
       () -> Catalogs.load("missing", conf));
 
-    Assertions.assertTrue(exc.getMessage().contains("Cannot find catalog plugin class"),
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.PLUGIN_CLASS_NOT_FOUND", exc.getCondition(),
       "Should complain that the class is not found");
     Assertions.assertTrue(exc.getMessage().contains("missing"),
       "Should identify the catalog by name");
@@ -127,7 +127,7 @@ public class CatalogLoadingSuite {
     SparkException exc = Assertions.assertThrows(SparkException.class,
       () -> Catalogs.load("invalid", conf));
 
-    Assertions.assertTrue(exc.getMessage().contains("does not implement CatalogPlugin"),
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.NOT_A_CATALOG_PLUGIN", exc.getCondition(),
       "Should complain that class does not implement CatalogPlugin");
     Assertions.assertTrue(exc.getMessage().contains("invalid"),
       "Should identify the catalog by name");
@@ -144,8 +144,7 @@ public class CatalogLoadingSuite {
     SparkException exc = Assertions.assertThrows(SparkException.class,
       () -> Catalogs.load("invalid", conf));
 
-    Assertions.assertTrue(
-      exc.getMessage().contains("Failed during instantiating constructor for catalog"),
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.CONSTRUCTOR_FAILURE", exc.getCondition(),
       "Should identify the constructor error");
     Assertions.assertTrue(exc.getCause().getMessage().contains("Expected failure"),
       "Should have expected error message");
@@ -160,14 +159,47 @@ public class CatalogLoadingSuite {
     SparkException exc = Assertions.assertThrows(SparkException.class,
       () -> Catalogs.load("invalid", conf));
 
-    Assertions.assertTrue(
-      exc.getMessage().contains("Failed to call public no-arg constructor for catalog"),
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.CONSTRUCTOR_NOT_ACCESSIBLE", exc.getCondition(),
       "Should complain that no public constructor is provided");
     Assertions.assertTrue(exc.getMessage().contains("invalid"),
       "Should identify the catalog by name");
     Assertions.assertTrue(exc.getMessage().contains(invalidClassName),
       "Should identify the class");
   }
+
+  @Test
+  public void testLoadNoNoArgConstructorCatalogPlugin() {
+    SQLConf conf = new SQLConf();
+    String invalidClassName = NoNoArgConstructorCatalogPlugin.class.getCanonicalName();
+    conf.setConfString("spark.sql.catalog.invalid", invalidClassName);
+
+    SparkException exc = Assertions.assertThrows(SparkException.class,
+      () -> Catalogs.load("invalid", conf));
+
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.CONSTRUCTOR_NOT_FOUND", exc.getCondition(),
+      "Should complain that no public no-arg constructor is found");
+    Assertions.assertTrue(exc.getMessage().contains("invalid"),
+      "Should identify the catalog by name");
+    Assertions.assertTrue(exc.getMessage().contains(invalidClassName),
+      "Should identify the class");
+  }
+
+  @Test
+  public void testLoadAbstractCatalogPlugin() {
+    SQLConf conf = new SQLConf();
+    String invalidClassName = AbstractCatalogPlugin.class.getCanonicalName();
+    conf.setConfString("spark.sql.catalog.invalid", invalidClassName);
+
+    SparkException exc = Assertions.assertThrows(SparkException.class,
+      () -> Catalogs.load("invalid", conf));
+
+    Assertions.assertEquals("CANNOT_LOAD_CATALOG.ABSTRACT_CLASS", exc.getCondition(),
+      "Should complain that the class is abstract");
+    Assertions.assertTrue(exc.getMessage().contains("invalid"),
+      "Should identify the catalog by name");
+    Assertions.assertTrue(exc.getMessage().contains(invalidClassName),
+      "Should identify the class");
+  }
 }
 
 class TestCatalogPlugin implements CatalogPlugin {
@@ -218,6 +250,25 @@ class AccessErrorCatalogPlugin implements CatalogPlugin { // no public construct
   }
 }
 
+class NoNoArgConstructorCatalogPlugin implements CatalogPlugin { // no public no-arg constructor
+  NoNoArgConstructorCatalogPlugin(String arg) {
+  }
+
+  @Override
+  public void initialize(String name, CaseInsensitiveStringMap options) {
+  }
+
+  @Override
+  public String name() {
+    return null;
+  }
+}
+
+abstract class AbstractCatalogPlugin implements CatalogPlugin { // abstract, cannot be instantiated
+  AbstractCatalogPlugin() {
+  }
+}
+
 class InvalidCatalogPlugin { // doesn't implement CatalogPlugin
   public void initialize(CaseInsensitiveStringMap options) {
   }
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/SupportsCatalogOptionsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/SupportsCatalogOptionsSuite.scala
index 98904e697607..bcd8ba185d1d 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/connector/SupportsCatalogOptionsSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/SupportsCatalogOptionsSuite.scala
@@ -285,7 +285,7 @@ class SupportsCatalogOptionsSuite extends SharedSparkSession with BeforeAndAfter
         sql(s"create table t1 (id bigint) using $format")
       }
 
-      assert(e.getMessage.contains("Cannot find catalog plugin class"))
+      assert(e.getMessage.contains("cannot find the plugin class"))
       assert(e.getMessage.contains("InvalidCatalogClass"))
     } finally {
       spark.sessionState.catalogManager.reset()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org