This is an automated email from the ASF dual-hosted git repository.
nastra pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/main by this push:
new c484d46fde Core, Spark: Rethrow ValidationException from REST 400
responses (#18473)
c484d46fde is described below
commit c484d46fde82028ed351e9a8f0b665261d7c1581
Author: raashed <[email protected]>
AuthorDate: Wed Nov 4 13:13:03 2026 +0530
Core, Spark: Rethrow ValidationException from REST 400 responses (#18473)
* Core, Spark: Rethrow ValidationException from REST 400 responses
The REST client turned every 400 into a BadRequestException, so a
ValidationException raised by the server surfaced as a different exception
than with the Hive or Hadoop catalogs. Like #9225 did for
IllegalArgumentException, DefaultErrorHandler now rethrows a
ValidationException when the error type matches. This lets
testCreateTableCommitProperties run against the REST catalog.
---
.../org/apache/iceberg/rest/ErrorHandlers.java | 3 ++
.../org/apache/iceberg/rest/TestErrorHandlers.java | 49 ++++++++++++++++++++++
.../apache/iceberg/spark/sql/TestCreateTable.java | 6 ---
.../apache/iceberg/spark/sql/TestCreateTable.java | 6 ---
.../apache/iceberg/spark/sql/TestCreateTable.java | 6 ---
.../apache/iceberg/spark/sql/TestCreateTable.java | 6 ---
6 files changed, 52 insertions(+), 24 deletions(-)
diff --git a/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
b/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
index 334bfde8ab..f28d589abe 100644
--- a/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
+++ b/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
@@ -36,6 +36,7 @@ import org.apache.iceberg.exceptions.NotFoundException;
import org.apache.iceberg.exceptions.RESTException;
import org.apache.iceberg.exceptions.ServiceFailureException;
import org.apache.iceberg.exceptions.ServiceUnavailableException;
+import org.apache.iceberg.exceptions.ValidationException;
import org.apache.iceberg.rest.auth.OAuth2Properties;
import org.apache.iceberg.rest.responses.ErrorResponse;
import org.apache.iceberg.rest.responses.ErrorResponseParser;
@@ -337,6 +338,8 @@ public class ErrorHandlers {
case 400:
if
(IllegalArgumentException.class.getSimpleName().equals(error.type())) {
throw new IllegalArgumentException(error.message());
+ } else if
(ValidationException.class.getSimpleName().equals(error.type())) {
+ throw new ValidationException("%s", error.message());
}
throw new BadRequestException("Malformed request: %s",
error.message());
case 401:
diff --git a/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
b/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
index b7bbe337cd..0f846c5808 100644
--- a/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
+++ b/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
@@ -20,11 +20,18 @@ package org.apache.iceberg.rest;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import org.apache.iceberg.exceptions.BadRequestException;
import org.apache.iceberg.exceptions.NoSuchWarehouseException;
import org.apache.iceberg.exceptions.RESTException;
import org.apache.iceberg.exceptions.ServiceFailureException;
+import org.apache.iceberg.exceptions.ValidationException;
import org.apache.iceberg.rest.responses.ErrorResponse;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
public class TestErrorHandlers {
@@ -71,6 +78,48 @@ public class TestErrorHandlers {
.hasMessage("Unable to process (code: 422, type: ValidationException):
null");
}
+ private static Stream<Arguments> handlersRethrowingValidationException() {
+ return Stream.of(
+ Arguments.of("defaultErrorHandler",
ErrorHandlers.defaultErrorHandler()),
+ Arguments.of("tableErrorHandler", ErrorHandlers.tableErrorHandler()),
+ Arguments.of("tableCommitHandler", ErrorHandlers.tableCommitHandler()),
+ Arguments.of("createTableErrorHandler",
ErrorHandlers.createTableErrorHandler()),
+ Arguments.of("viewErrorHandler", ErrorHandlers.viewErrorHandler()),
+ Arguments.of("viewCommitHandler", ErrorHandlers.viewCommitHandler()),
+ Arguments.of("planErrorHandler", ErrorHandlers.planErrorHandler()),
+ Arguments.of("planTaskHandler", ErrorHandlers.planTaskHandler()),
+ Arguments.of("configErrorHandler",
ErrorHandlers.configErrorHandler()));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("handlersRethrowingValidationException")
+ void badRequestWithValidationExceptionType(String name,
Consumer<ErrorResponse> handler) {
+ ErrorResponse error =
+ ErrorResponse.builder()
+ .responseCode(400)
+ .withType("ValidationException")
+ .withMessage("Table property commit.retry.num-retries must have
integer value")
+ .build();
+
+ assertThatThrownBy(() -> handler.accept(error))
+ .isInstanceOf(ValidationException.class)
+ .hasMessage("Table property commit.retry.num-retries must have integer
value");
+ }
+
+ @Test
+ void badRequestWithOtherType() {
+ ErrorResponse error =
+ ErrorResponse.builder()
+ .responseCode(400)
+ .withType("BadRequestException")
+ .withMessage("Invalid input")
+ .build();
+
+ assertThatThrownBy(() -> ErrorHandlers.defaultErrorHandler().accept(error))
+ .isInstanceOf(BadRequestException.class)
+ .hasMessage("Malformed request: Invalid input");
+ }
+
@Test
public void testConfigErrorHandler404ThrowsNoSuchWarehouseException() {
ErrorResponse error =
diff --git
a/spark/v3.5/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
b/spark/v3.5/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
index afb4e99648..6a9f9583de 100644
---
a/spark/v3.5/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
+++
b/spark/v3.5/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
@@ -18,8 +18,6 @@
*/
package org.apache.iceberg.spark.sql;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE_REST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assumptions.assumeThat;
@@ -341,10 +339,6 @@ public class TestCreateTable extends CatalogTestBase {
@TestTemplate
public void testCreateTableCommitProperties() {
- assumeThat(catalogConfig.get(ICEBERG_CATALOG_TYPE))
- .as(
- "need to fix https://github.com/apache/iceberg/issues/11554 before
enabling this for the REST catalog")
- .isNotEqualTo(ICEBERG_CATALOG_TYPE_REST);
assertThat(validationCatalog.tableExists(tableIdent))
.as("Table should not already exist")
.isFalse();
diff --git
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
index afb4e99648..6a9f9583de 100644
---
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
+++
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
@@ -18,8 +18,6 @@
*/
package org.apache.iceberg.spark.sql;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE_REST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assumptions.assumeThat;
@@ -341,10 +339,6 @@ public class TestCreateTable extends CatalogTestBase {
@TestTemplate
public void testCreateTableCommitProperties() {
- assumeThat(catalogConfig.get(ICEBERG_CATALOG_TYPE))
- .as(
- "need to fix https://github.com/apache/iceberg/issues/11554 before
enabling this for the REST catalog")
- .isNotEqualTo(ICEBERG_CATALOG_TYPE_REST);
assertThat(validationCatalog.tableExists(tableIdent))
.as("Table should not already exist")
.isFalse();
diff --git
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
index afb4e99648..6a9f9583de 100644
---
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
+++
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
@@ -18,8 +18,6 @@
*/
package org.apache.iceberg.spark.sql;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE_REST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assumptions.assumeThat;
@@ -341,10 +339,6 @@ public class TestCreateTable extends CatalogTestBase {
@TestTemplate
public void testCreateTableCommitProperties() {
- assumeThat(catalogConfig.get(ICEBERG_CATALOG_TYPE))
- .as(
- "need to fix https://github.com/apache/iceberg/issues/11554 before
enabling this for the REST catalog")
- .isNotEqualTo(ICEBERG_CATALOG_TYPE_REST);
assertThat(validationCatalog.tableExists(tableIdent))
.as("Table should not already exist")
.isFalse();
diff --git
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
index 10ac453c84..48aacdc19a 100644
---
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
+++
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
@@ -18,8 +18,6 @@
*/
package org.apache.iceberg.spark.sql;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE;
-import static org.apache.iceberg.CatalogUtil.ICEBERG_CATALOG_TYPE_REST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assumptions.assumeThat;
@@ -665,10 +663,6 @@ public class TestCreateTable extends CatalogTestBase {
@TestTemplate
public void testCreateTableCommitProperties() {
- assumeThat(catalogConfig.get(ICEBERG_CATALOG_TYPE))
- .as(
- "need to fix https://github.com/apache/iceberg/issues/11554 before
enabling this for the REST catalog")
- .isNotEqualTo(ICEBERG_CATALOG_TYPE_REST);
assertThat(validationCatalog.tableExists(tableIdent))
.as("Table should not already exist")
.isFalse();