FANNG1 opened a new issue, #14204:
URL: https://github.com/apache/gravitino/issues/14204

   ### What would you like to be improved?
   
   The lance-rest-server implements a subset of the Lance namespace REST spec. 
Routes that are part of the spec but not implemented here — e.g. 
`/v1/table/{id}/query`, `/v1/table/{id}/create_index`, 
`/v1/table/{id}/index/list`, `/v1/table/{id}/index/{index_name}/drop` — fail 
resource matching in Jersey (which is mounted at `/lance/*` and only scans the 
registered resources in `LanceTableOperations` / `LanceNamespaceOperations`). 
The request never reaches a handler that can produce a Lance `ErrorResponse`, 
so the client receives the container's default HTML error page:
   
   ```
   InternalException{code=18, message='Internal error: Failed to parse error 
response:
   status=404 Not Found, body=<html>...'}
     at org.lance.namespace.RestNamespace.queryTable(RestNamespace.java:377)
   ```
   
   This is not spec-compliant, and it makes client-side failures undiagnosable 
— a deliberately unimplemented operation looks identical to a wrong endpoint or 
a misconfigured URI.
   
   The spec already defines exactly how this should be reported (checked 
against lance-namespace `v0.11.1`, the version we depend on; unchanged in 
`v0.13.0`):
   
   - `docs/src/namespace/operations/errors.md` → **Common Errors**: *"All 
operations may return … **0 (Unsupported)**: The operation is not supported by 
this backend"*
   - `docs/src/namespace/supported-catalogs/lance-rest.md` → **Error Code to 
HTTP Status Mapping**: *"REST Catalog implementations **must** map … Error code 
`0` (Unsupported) to HTTP `406 Not Acceptable`"*
   - `spec.yaml` provides the `ErrorResponse` model (required numeric `code`) 
and a ready-made `UnsupportedOperationErrorResponse` (406)
   
   The response body is what actually matters to clients. The Rust REST client 
classifies errors solely from the body's `code` field and ignores the HTTP 
status (`lance/rust/lance-namespace-impls/src/rest.rs`, `parse_error_response`: 
*"The error code is the sole source of truth for error classification"*); 
`NamespaceError::from_code(0)` yields `Unsupported`. The Java client behaves 
the same way via `ErrorFactory.fromErrorCode(0)` → 
`org.lance.namespace.errors.UnsupportedOperationException`. So returning 
`{"code": 0, ...}` turns today's opaque `Internal` failure into a typed, 
actionable error — which is the signal a connector needs in order to fall back 
to a local execution path.
   
   Gravitino's error plumbing is already in place: `LanceExceptionMapper` maps 
`UnsupportedOperationException` to 
`org.lance.namespace.errors.UnsupportedOperationException` → HTTP 406 with a 
well-formed `ErrorResponse`. The only gap is that unmatched routes never reach 
it.
   
   Reported downstream in #14200; same boundary as #13065.
   
   ### How should we improve?
   
   1. Make unmatched routes under the Lance REST servlet produce a 
spec-compliant error instead of the container default. Preferred: handle JAX-RS 
`javax.ws.rs.NotFoundException` in `LanceExceptionMapper` and map it to code 
`0` (Unsupported) / HTTP 406 — this covers every unimplemented spec route at 
once, and is unambiguous here because entity-not-found cases throw Gravitino's 
own `NotFoundException` / `NoSuchTableException`. Alternative: explicit stub 
methods per unimplemented route that throw `UnsupportedOperationException`.
   2. Include the operation name and path in the error message / `instance` so 
clients can tell *which* operation is unsupported.
   3. Add unit tests asserting that a request to an unimplemented route returns 
HTTP 406 with a JSON `ErrorResponse` carrying `code: 0`.
   4. Upstream follow-up (lance-namespace): the normative prose says any 
operation may return code `0`, but at the OpenAPI path level only 
`/v1/namespace/{id}/create`, `/v1/namespace/{id}/list`, 
`/v1/namespace/{id}/table/list` and `/v1/table/{id}/register` declare a 406 
response. `/v1/table/{id}/query` and the index routes do not. Worth a spec PR 
to add `UnsupportedOperationErrorResponse` to those paths.
   


-- 
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