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();

Reply via email to