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