travis-bowen opened a new pull request, #4404:
URL: https://github.com/apache/polaris/pull/4404

   ## Motivation
   
   `RateLimiterFilter` previously returned HTTP 429 with an empty body and no 
`Content-Type` header:
   
   ```java
   ctx.abortWith(Response.status(Response.Status.TOO_MANY_REQUESTS).build());
   ```
   
   Iceberg REST clients (pyiceberg, Spark, and any third-party caller) cannot 
meaningfully parse this. The Iceberg Java client's 
`DefaultErrorHandler.parseResponse()` attempts 
`ErrorResponseParser.fromJson("")` on the empty body, catches the JSON parse 
failure, and falls back to building an `ErrorResponse` with `message = ""`. 
Since there is no `case 429:` in any `ErrorHandlers` switch, the result is 
always:
   
   ```
   RESTException("Unable to process: ")
   ```
   
   — an opaque error with no actionable context for the caller.
   
   ## Changes
   
   Add an Iceberg-compatible `ErrorResponse` JSON body to the 429 response, 
following the exact pattern already used by `IcebergExceptionMapper` for all 
other error codes:
   
   ```java
   ctx.abortWith(
       Response.status(Response.Status.TOO_MANY_REQUESTS)
           .type(MediaType.APPLICATION_JSON_TYPE)
           .entity(
               ErrorResponse.builder()
                   
.responseCode(Response.Status.TOO_MANY_REQUESTS.getStatusCode())
                   .withType("RateLimitExceededException")
                   .withMessage("Rate exceeded")
                   .build())
           .build());
   ```
   
   ## Ecosystem Context
   
   The Iceberg REST OpenAPI spec does not define a 429 response schema — 
implementations are on their own. Surveying the major catalog implementations:
   
   | Implementation | Body on 429? | Follows Iceberg `ErrorModel`? |
   |---|---|---|
   | AWS Glue | Yes | No (AWS `{"__type": "ThrottlingException", ...}` format) |
   | Apache Nessie | Yes | No (Nessie `{"status": 429, "errorCode": 
"TOO_MANY_REQUESTS", ...}` format) |
   | Databricks Unity Catalog | Yes | No (Databricks `{"error_code": 
"RESOURCE_EXHAUSTED", ...}` format) |
   | Apache Polaris (this fix) | Yes | **Yes** |
   
   All other catalogs return *some* JSON, but none follow the Iceberg 
`ErrorModel` schema. With this fix, Polaris becomes the most spec-consistent 
implementation — clients using `ErrorResponseParser` will be able to round-trip 
the 429 body correctly.
   
   ## Compatibility
   
   - Existing clients that ignore the 429 body are unaffected.
   - Clients that previously hit the empty-body parse failure will now receive 
a well-formed `ErrorResponse`.
   - No change to status code or any other behavior.
   
   ## Tests
   
   Added `testRateLimitedResponseHasIcebergErrorBody` — a full integration test 
that performs a live HTTP request against a rate-limited endpoint, reads the 
response body, and round-trips it through `ErrorResponseParser.fromJson(...)` 
to prove Iceberg client compatibility. Asserts `Content-Type: 
application/json`, `code == 429`, `type == "RateLimitExceededException"`, and 
`message` contains `"Rate exceeded"`.
   
   Fixes #4402
   
   ---
   
   > This fix was developed with AI assistance (Claude). The author has 
reviewed the change end-to-end and takes full responsibility for correctness 
and ASF licensing compliance.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to