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

kevinjqliu 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 17fc6da837 API, Core: Handle 404 from /v1/config for missing 
warehouses (#16059)
17fc6da837 is described below

commit 17fc6da837442443421cfbac01ff2941a820ba20
Author: Oguzhan Unlu <[email protected]>
AuthorDate: Thu May 7 23:32:30 2026 +0300

    API, Core: Handle 404 from /v1/config for missing warehouses (#16059)
    
    * API, Core: Handle 404 from /v1/config for missing warehouses
    
    Add NoSuchWarehouseException and configErrorHandler that throws it on
    404 responses with a valid error type, distinguishing missing warehouses
    from misconfigured URIs. Update RESTSessionCatalog to use the new
    handler for config calls.
    
    * move tests
---
 .../exceptions/NoSuchWarehouseException.java       | 34 ++++++++++++++++++++
 .../org/apache/iceberg/rest/ErrorHandlers.java     | 19 ++++++++++++
 .../apache/iceberg/rest/RESTSessionCatalog.java    |  2 +-
 .../org/apache/iceberg/rest/TestErrorHandlers.java | 36 ++++++++++++++++++++++
 4 files changed, 90 insertions(+), 1 deletion(-)

diff --git 
a/api/src/main/java/org/apache/iceberg/exceptions/NoSuchWarehouseException.java 
b/api/src/main/java/org/apache/iceberg/exceptions/NoSuchWarehouseException.java
new file mode 100644
index 0000000000..94ae50cd1c
--- /dev/null
+++ 
b/api/src/main/java/org/apache/iceberg/exceptions/NoSuchWarehouseException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iceberg.exceptions;
+
+import com.google.errorprone.annotations.FormatMethod;
+
+/** Exception raised when attempting to load a warehouse that does not exist. 
*/
+public class NoSuchWarehouseException extends RuntimeException {
+  @FormatMethod
+  public NoSuchWarehouseException(String message, Object... args) {
+    super(String.format(message, args));
+  }
+
+  @FormatMethod
+  public NoSuchWarehouseException(Throwable cause, String message, Object... 
args) {
+    super(String.format(message, args), cause);
+  }
+}
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 791eb732bb..334bfde8ab 100644
--- a/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
+++ b/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
@@ -30,6 +30,7 @@ import org.apache.iceberg.exceptions.NoSuchPlanIdException;
 import org.apache.iceberg.exceptions.NoSuchPlanTaskException;
 import org.apache.iceberg.exceptions.NoSuchTableException;
 import org.apache.iceberg.exceptions.NoSuchViewException;
+import org.apache.iceberg.exceptions.NoSuchWarehouseException;
 import org.apache.iceberg.exceptions.NotAuthorizedException;
 import org.apache.iceberg.exceptions.NotFoundException;
 import org.apache.iceberg.exceptions.RESTException;
@@ -92,6 +93,10 @@ public class ErrorHandlers {
     return DefaultErrorHandler.INSTANCE;
   }
 
+  public static Consumer<ErrorResponse> configErrorHandler() {
+    return ConfigErrorHandler.INSTANCE;
+  }
+
   public static Consumer<ErrorResponse> oauthErrorHandler() {
     return OAuthErrorHandler.INSTANCE;
   }
@@ -295,6 +300,20 @@ public class ErrorHandlers {
     }
   }
 
+  /** Request error handler for config endpoint. */
+  private static class ConfigErrorHandler extends DefaultErrorHandler {
+    private static final ErrorHandler INSTANCE = new ConfigErrorHandler();
+
+    @Override
+    public void accept(ErrorResponse error) {
+      if (error.code() == 404 && error.type() != null) {
+        throw new NoSuchWarehouseException("%s", error.message());
+      }
+
+      super.accept(error);
+    }
+  }
+
   /**
    * Request error handler that handles the common cases that are included 
with all responses, such
    * as 400, 500, etc.
diff --git a/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java 
b/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
index c7b5b5d41c..ec30d9de89 100644
--- a/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
+++ b/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
@@ -1338,7 +1338,7 @@ public class RESTSessionCatalog extends 
BaseViewSessionCatalog
                 queryParams.build(),
                 ConfigResponse.class,
                 RESTUtil.configHeaders(properties),
-                ErrorHandlers.defaultErrorHandler());
+                ErrorHandlers.configErrorHandler());
     configResponse.validate();
     return configResponse;
   }
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 8bf62c3c6c..b7bbe337cd 100644
--- a/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
+++ b/core/src/test/java/org/apache/iceberg/rest/TestErrorHandlers.java
@@ -20,7 +20,9 @@ package org.apache.iceberg.rest;
 
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import org.apache.iceberg.exceptions.NoSuchWarehouseException;
 import org.apache.iceberg.exceptions.RESTException;
+import org.apache.iceberg.exceptions.ServiceFailureException;
 import org.apache.iceberg.rest.responses.ErrorResponse;
 import org.junit.jupiter.api.Test;
 
@@ -68,4 +70,38 @@ public class TestErrorHandlers {
         .isInstanceOf(RESTException.class)
         .hasMessage("Unable to process (code: 422, type: ValidationException): 
null");
   }
+
+  @Test
+  public void testConfigErrorHandler404ThrowsNoSuchWarehouseException() {
+    ErrorResponse error =
+        ErrorResponse.builder()
+            .responseCode(404)
+            .withType("NotFoundException")
+            .withMessage("Warehouse not found")
+            .build();
+
+    assertThatThrownBy(() -> ErrorHandlers.configErrorHandler().accept(error))
+        .isInstanceOf(NoSuchWarehouseException.class)
+        .hasMessage("Warehouse not found");
+  }
+
+  @Test
+  public void testConfigErrorHandler404ForMisconfiguredUri() {
+    ErrorResponse error =
+        ErrorResponse.builder().responseCode(404).withMessage("Not 
Found").build();
+
+    assertThatThrownBy(() -> ErrorHandlers.configErrorHandler().accept(error))
+        .isInstanceOf(RESTException.class)
+        .hasMessageContaining("Not Found");
+  }
+
+  @Test
+  public void testConfigErrorHandlerDelegatesToDefaultForNon404() {
+    ErrorResponse error =
+        ErrorResponse.builder().responseCode(500).withMessage("Internal server 
error").build();
+
+    assertThatThrownBy(() -> ErrorHandlers.configErrorHandler().accept(error))
+        .isInstanceOf(ServiceFailureException.class)
+        .hasMessageContaining("Internal server error");
+  }
 }

Reply via email to