From 0bd8478d2507fc3cd04c92b632f89b76fa9d1dea Mon Sep 17 00:00:00 2001 From: Harshita Joshi Date: Fri, 31 Jul 2026 01:49:50 -0500 Subject: [PATCH 1/3] Delegate HTTP status resolution from PolarisExceptionMapper to PolarisException hierarchy Fixes #5167 --- .../exceptions/AlreadyExistsException.java | 5 +++ .../exceptions/CommitConflictException.java | 5 +++ .../core/exceptions/PolarisException.java | 10 +++++ .../PolarisServiceUnavailableException.java | 5 +++ .../PolicyMappingAlreadyExistsException.java | 5 +++ .../exceptions/NoSuchPolicyException.java | 5 +++ .../exceptions/PolicyAttachException.java | 5 +++ .../exceptions/PolicyInUseException.java | 5 +++ .../PolicyVersionMismatchException.java | 5 +++ .../validator/InvalidPolicyException.java | 5 +++ .../exception/PolarisExceptionMapper.java | 39 +++---------------- .../exception/ExceptionMapperTest.java | 32 +++++++++++++++ 12 files changed, 93 insertions(+), 33 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java index a941a549cf0..4ce753e5b8a 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java @@ -30,4 +30,9 @@ public AlreadyExistsException(String message) { public AlreadyExistsException(String message, Throwable cause) { super(message, cause); } + + @Override + public int httpStatusCode() { + return 409; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java index a1e11cd0038..f556f85b906 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java @@ -39,4 +39,9 @@ public CommitConflictException(Throwable cause, String message, Object... args) public CommitConflictException(String message, Throwable cause) { super(message, cause); } + + @Override + public int httpStatusCode() { + return 409; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java index 96ef9cf7c38..e2366301bfb 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java @@ -22,6 +22,7 @@ * Base class for Polaris-specific runtime exceptions. * *

All custom exceptions in Polaris should extend this class to provide specific error details. + * Subclasses override {@link #httpStatusCode()} to declare their HTTP response status. */ public abstract class PolarisException extends RuntimeException { @@ -32,4 +33,13 @@ public PolarisException(String message) { public PolarisException(String message, Throwable cause) { super(message, cause); } + + /** + * Returns the HTTP status code that should be used when this exception is mapped to an HTTP + * response. Defaults to {@code 500} (Internal Server Error). Subclasses should override this to + * return a more specific status code. + */ + public int httpStatusCode() { + return 500; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java index 5479fd9f94b..fec50ca3587 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java @@ -37,4 +37,9 @@ public PolarisServiceUnavailableException(int retryAfterSeconds, String message, public int getRetryAfterSeconds() { return retryAfterSeconds; } + + @Override + public int httpStatusCode() { + return 503; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java index a31e500b0b3..e59d9595c26 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java @@ -45,4 +45,9 @@ public PolicyMappingAlreadyExistsException(String message, Object... arg) { public PolarisPolicyMappingRecord getExistingRecord() { return this.existingRecord; } + + @Override + public int httpStatusCode() { + return 409; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java index 642bd36adb3..118b7672e95 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java @@ -29,4 +29,9 @@ public NoSuchPolicyException(String message) { public NoSuchPolicyException(String message, Throwable cause) { super(message, cause); } + + @Override + public int httpStatusCode() { + return 404; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java index e47d978d0fd..3c812557d1a 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java @@ -31,4 +31,9 @@ public PolicyAttachException(String message, Object... args) { public PolicyAttachException(Throwable cause, String message, Object... args) { super(String.format(message, args), cause); } + + @Override + public int httpStatusCode() { + return 400; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java index 14d165497e1..3ac632f6c92 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java @@ -31,4 +31,9 @@ public PolicyInUseException(String message, Object... args) { public PolicyInUseException(Throwable cause, String message, Object... args) { super(String.format(message, args), cause); } + + @Override + public int httpStatusCode() { + return 400; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java index c2f8f8f78e1..f783efb40cc 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java @@ -28,4 +28,9 @@ public PolicyVersionMismatchException(String message) { public PolicyVersionMismatchException(String message, Throwable cause) { super(message, cause); } + + @Override + public int httpStatusCode() { + return 409; + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java index 9672cfa617b..c3d20743ab8 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java @@ -33,4 +33,9 @@ public InvalidPolicyException(String message, Throwable cause) { public InvalidPolicyException(Throwable cause) { super("Invalid policy", cause); } + + @Override + public int httpStatusCode() { + return 400; + } } diff --git a/runtime/service/src/main/java/org/apache/polaris/service/exception/PolarisExceptionMapper.java b/runtime/service/src/main/java/org/apache/polaris/service/exception/PolarisExceptionMapper.java index 97d77de7dbd..b3ed74bf299 100644 --- a/runtime/service/src/main/java/org/apache/polaris/service/exception/PolarisExceptionMapper.java +++ b/runtime/service/src/main/java/org/apache/polaris/service/exception/PolarisExceptionMapper.java @@ -25,64 +25,37 @@ import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; import org.apache.iceberg.rest.responses.ErrorResponse; -import org.apache.polaris.core.exceptions.AlreadyExistsException; -import org.apache.polaris.core.exceptions.CommitConflictException; import org.apache.polaris.core.exceptions.PolarisException; import org.apache.polaris.core.exceptions.PolarisServiceUnavailableException; -import org.apache.polaris.core.persistence.PolicyMappingAlreadyExistsException; -import org.apache.polaris.core.policy.exceptions.NoSuchPolicyException; -import org.apache.polaris.core.policy.exceptions.PolicyAttachException; -import org.apache.polaris.core.policy.exceptions.PolicyInUseException; -import org.apache.polaris.core.policy.exceptions.PolicyVersionMismatchException; -import org.apache.polaris.core.policy.validator.InvalidPolicyException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.event.Level; /** - * An {@link ExceptionMapper} implementation for {@link PolarisException}s modeled after {@link - * IcebergExceptionMapper} + * An {@link ExceptionMapper} implementation for {@link PolarisException}s. Delegates HTTP status + * resolution to {@link PolarisException#httpStatusCode()}. */ @Provider public class PolarisExceptionMapper implements ExceptionMapper { private static final Logger LOGGER = LoggerFactory.getLogger(PolarisExceptionMapper.class); - private Response.Status getStatus(PolarisException exception) { - return switch (exception) { - case PolarisServiceUnavailableException polarisServiceUnavailableException -> - Response.Status.SERVICE_UNAVAILABLE; - case AlreadyExistsException alreadyExistsException -> Response.Status.CONFLICT; - case CommitConflictException commitConflictException -> Response.Status.CONFLICT; - case InvalidPolicyException invalidPolicyException -> Response.Status.BAD_REQUEST; - case PolicyAttachException policyAttachException -> Response.Status.BAD_REQUEST; - case NoSuchPolicyException noSuchPolicyException -> Response.Status.NOT_FOUND; - case PolicyVersionMismatchException policyVersionMismatchException -> - Response.Status.CONFLICT; - case PolicyMappingAlreadyExistsException policyMappingAlreadyExistsException -> - Response.Status.CONFLICT; - case PolicyInUseException policyInUseException -> Response.Status.BAD_REQUEST; - default -> Response.Status.INTERNAL_SERVER_ERROR; - }; - } - @Override public Response toResponse(PolarisException exception) { - Response.Status status = getStatus(exception); + int statusCode = exception.httpStatusCode(); getLogger() - .atLevel( - status.getFamily() == Response.Status.Family.SERVER_ERROR ? Level.INFO : Level.DEBUG) + .atLevel(statusCode >= 500 ? Level.INFO : Level.DEBUG) .setCause(exception) .log("Full PolarisException"); ErrorResponse errorResponse = ErrorResponse.builder() - .responseCode(status.getStatusCode()) + .responseCode(statusCode) .withType(exception.getClass().getSimpleName()) .withMessage(exception.getMessage()) .build(); Response.ResponseBuilder builder = - Response.status(status).entity(errorResponse).type(MediaType.APPLICATION_JSON_TYPE); + Response.status(statusCode).entity(errorResponse).type(MediaType.APPLICATION_JSON_TYPE); if (exception instanceof PolarisServiceUnavailableException e && e.getRetryAfterSeconds() != 0) { builder.header(HttpHeaders.RETRY_AFTER, e.getRetryAfterSeconds()); diff --git a/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java b/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java index 4520b7bf841..d7266a307aa 100644 --- a/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java +++ b/runtime/service/src/test/java/org/apache/polaris/service/exception/ExceptionMapperTest.java @@ -38,7 +38,15 @@ import org.apache.iceberg.exceptions.RuntimeIOException; import org.apache.polaris.core.exceptions.AlreadyExistsException; import org.apache.polaris.core.exceptions.CommitConflictException; +import org.apache.polaris.core.exceptions.FileIOUnknownHostException; +import org.apache.polaris.core.exceptions.PolarisException; import org.apache.polaris.core.exceptions.PolarisServiceUnavailableException; +import org.apache.polaris.core.persistence.PolicyMappingAlreadyExistsException; +import org.apache.polaris.core.policy.exceptions.NoSuchPolicyException; +import org.apache.polaris.core.policy.exceptions.PolicyAttachException; +import org.apache.polaris.core.policy.exceptions.PolicyInUseException; +import org.apache.polaris.core.policy.exceptions.PolicyVersionMismatchException; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; import org.jboss.logmanager.Level; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -111,6 +119,30 @@ public void testServiceUnavailableWithRetryAfter() { assertThat(response.getHeaderString(HttpHeaders.RETRY_AFTER)).isEqualTo("3"); } + @ParameterizedTest + @MethodSource("polarisExceptionStatusCodes") + public void testPolarisExceptionStatusCodes(PolarisException exception, int expectedStatus) { + assertThat(exception.httpStatusCode()).isEqualTo(expectedStatus); + + PolarisExceptionMapper mapper = new PolarisExceptionMapper(); + Response response = mapper.toResponse(exception); + assertThat(response.getStatus()).isEqualTo(expectedStatus); + } + + static Stream polarisExceptionStatusCodes() { + return Stream.of( + Arguments.of(new AlreadyExistsException("msg"), 409), + Arguments.of(new CommitConflictException("msg"), 409), + Arguments.of(new PolarisServiceUnavailableException(0, "msg"), 503), + Arguments.of(new InvalidPolicyException("msg"), 400), + Arguments.of(new PolicyAttachException("msg"), 400), + Arguments.of(new PolicyInUseException("msg"), 400), + Arguments.of(new NoSuchPolicyException("msg"), 404), + Arguments.of(new PolicyVersionMismatchException("msg"), 409), + Arguments.of(new PolicyMappingAlreadyExistsException("msg"), 409), + Arguments.of(new FileIOUnknownHostException("msg", new RuntimeException()), 500)); + } + static Stream testFullExceptionIsLogged() { // ConstraintViolationException isn't included because it doesn't propagate any info to its // inherited Exception From 121e0e24882be06a9722962e24fa23c1d475f8c0 Mon Sep 17 00:00:00 2001 From: Harshita Joshi Date: Tue, 4 Aug 2026 15:59:27 -0500 Subject: [PATCH 2/3] Use Response.Status constants instead of raw int HTTP status codes --- .../polaris/core/exceptions/AlreadyExistsException.java | 4 +++- .../polaris/core/exceptions/CommitConflictException.java | 3 ++- .../org/apache/polaris/core/exceptions/PolarisException.java | 4 +++- .../core/exceptions/PolarisServiceUnavailableException.java | 3 ++- .../core/persistence/PolicyMappingAlreadyExistsException.java | 3 ++- .../polaris/core/policy/exceptions/NoSuchPolicyException.java | 3 ++- .../polaris/core/policy/exceptions/PolicyAttachException.java | 3 ++- .../polaris/core/policy/exceptions/PolicyInUseException.java | 3 ++- .../policy/exceptions/PolicyVersionMismatchException.java | 3 ++- .../polaris/core/policy/validator/InvalidPolicyException.java | 3 ++- 10 files changed, 22 insertions(+), 10 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java index 4ce753e5b8a..72511b10da6 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/AlreadyExistsException.java @@ -18,6 +18,8 @@ */ package org.apache.polaris.core.exceptions; +import jakarta.ws.rs.core.Response; + /** * A {@link PolarisException} implementation for when Polaris is unable to create an entity that * already exists. @@ -33,6 +35,6 @@ public AlreadyExistsException(String message, Throwable cause) { @Override public int httpStatusCode() { - return 409; + return Response.Status.CONFLICT.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java index f556f85b906..d643f7a9e9a 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/CommitConflictException.java @@ -20,6 +20,7 @@ package org.apache.polaris.core.exceptions; import com.google.errorprone.annotations.FormatMethod; +import jakarta.ws.rs.core.Response; public class CommitConflictException extends PolarisException { public CommitConflictException(String message) { @@ -42,6 +43,6 @@ public CommitConflictException(String message, Throwable cause) { @Override public int httpStatusCode() { - return 409; + return Response.Status.CONFLICT.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java index e2366301bfb..b1b6df6282b 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java @@ -18,6 +18,8 @@ */ package org.apache.polaris.core.exceptions; +import jakarta.ws.rs.core.Response; + /** * Base class for Polaris-specific runtime exceptions. * @@ -40,6 +42,6 @@ public PolarisException(String message, Throwable cause) { * return a more specific status code. */ public int httpStatusCode() { - return 500; + return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java index fec50ca3587..fa596bf2875 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisServiceUnavailableException.java @@ -19,6 +19,7 @@ package org.apache.polaris.core.exceptions; import com.google.errorprone.annotations.FormatMethod; +import jakarta.ws.rs.core.Response; /** * Signals a transient failure that the client may resolve by retrying. Mapped to HTTP 503 (Service @@ -40,6 +41,6 @@ public int getRetryAfterSeconds() { @Override public int httpStatusCode() { - return 503; + return Response.Status.SERVICE_UNAVAILABLE.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java index e59d9595c26..9223fa91909 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolicyMappingAlreadyExistsException.java @@ -19,6 +19,7 @@ package org.apache.polaris.core.persistence; import com.google.errorprone.annotations.FormatMethod; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; import org.apache.polaris.core.policy.PolarisPolicyMappingRecord; @@ -48,6 +49,6 @@ public PolarisPolicyMappingRecord getExistingRecord() { @Override public int httpStatusCode() { - return 409; + return Response.Status.CONFLICT.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java index 118b7672e95..a9157d04dc0 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/NoSuchPolicyException.java @@ -18,6 +18,7 @@ */ package org.apache.polaris.core.policy.exceptions; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; public class NoSuchPolicyException extends PolarisException { @@ -32,6 +33,6 @@ public NoSuchPolicyException(String message, Throwable cause) { @Override public int httpStatusCode() { - return 404; + return Response.Status.NOT_FOUND.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java index 3c812557d1a..cc24b6f70ad 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyAttachException.java @@ -19,6 +19,7 @@ package org.apache.polaris.core.policy.exceptions; import com.google.errorprone.annotations.FormatMethod; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; public class PolicyAttachException extends PolarisException { @@ -34,6 +35,6 @@ public PolicyAttachException(Throwable cause, String message, Object... args) { @Override public int httpStatusCode() { - return 400; + return Response.Status.BAD_REQUEST.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java index 3ac632f6c92..616a01e7e80 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyInUseException.java @@ -19,6 +19,7 @@ package org.apache.polaris.core.policy.exceptions; import com.google.errorprone.annotations.FormatMethod; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; public class PolicyInUseException extends PolarisException { @@ -34,6 +35,6 @@ public PolicyInUseException(Throwable cause, String message, Object... args) { @Override public int httpStatusCode() { - return 400; + return Response.Status.BAD_REQUEST.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java index f783efb40cc..95b10040205 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/exceptions/PolicyVersionMismatchException.java @@ -18,6 +18,7 @@ */ package org.apache.polaris.core.policy.exceptions; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; public class PolicyVersionMismatchException extends PolarisException { @@ -31,6 +32,6 @@ public PolicyVersionMismatchException(String message, Throwable cause) { @Override public int httpStatusCode() { - return 409; + return Response.Status.CONFLICT.getStatusCode(); } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java index c3d20743ab8..e91d0c735ee 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/InvalidPolicyException.java @@ -18,6 +18,7 @@ */ package org.apache.polaris.core.policy.validator; +import jakarta.ws.rs.core.Response; import org.apache.polaris.core.exceptions.PolarisException; /** Exception thrown when a policy is invalid or violates defined rules. */ @@ -36,6 +37,6 @@ public InvalidPolicyException(Throwable cause) { @Override public int httpStatusCode() { - return 400; + return Response.Status.BAD_REQUEST.getStatusCode(); } } From 03e5c503be5046d5fcb2939d056936ddfacdcb29 Mon Sep 17 00:00:00 2001 From: Harshita Joshi Date: Fri, 7 Aug 2026 18:09:47 -0500 Subject: [PATCH 3/3] Make httpStatusCode() abstract so every exception declares its own status FileIOUnknownHostException was the only subclass relying on the inherited default. It now returns 500 explicitly, preserving current runtime behavior. --- .../core/exceptions/FileIOUnknownHostException.java | 7 +++++++ .../polaris/core/exceptions/PolarisException.java | 11 +++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/FileIOUnknownHostException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/FileIOUnknownHostException.java index 2e830205afa..9fa26bb74b0 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/FileIOUnknownHostException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/FileIOUnknownHostException.java @@ -18,6 +18,8 @@ */ package org.apache.polaris.core.exceptions; +import jakarta.ws.rs.core.Response; + /** * A {@link PolarisException} implementation for when an UnknownHostException happens during File IO * to S3, GCS, or Azure. @@ -26,4 +28,9 @@ public class FileIOUnknownHostException extends PolarisException { public FileIOUnknownHostException(String message, Throwable cause) { super(message, cause); } + + @Override + public int httpStatusCode() { + return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); + } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java index b1b6df6282b..80151f4a593 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/exceptions/PolarisException.java @@ -18,13 +18,11 @@ */ package org.apache.polaris.core.exceptions; -import jakarta.ws.rs.core.Response; - /** * Base class for Polaris-specific runtime exceptions. * *

All custom exceptions in Polaris should extend this class to provide specific error details. - * Subclasses override {@link #httpStatusCode()} to declare their HTTP response status. + * Subclasses must implement {@link #httpStatusCode()} to declare their HTTP response status. */ public abstract class PolarisException extends RuntimeException { @@ -38,10 +36,7 @@ public PolarisException(String message, Throwable cause) { /** * Returns the HTTP status code that should be used when this exception is mapped to an HTTP - * response. Defaults to {@code 500} (Internal Server Error). Subclasses should override this to - * return a more specific status code. + * response. */ - public int httpStatusCode() { - return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); - } + public abstract int httpStatusCode(); }