Repository navigation
fix(client): throw DoclingServeClientException for a 422 without validation details - #714
Merged
edeandrea merged 1 commit intoSep 29, 2026
Conversation
…dation details
A 422 response whose body is a JSON object without validation details (for example {}, {"error":"..."} or {"detail":[]}) was deserialized into an empty ValidationError and thrown as a ValidationException with a blank message, losing the response body. Treat a ValidationError without details as not being a validation error and throw the generic DoclingServeClientException, which keeps the status code and the response body.
Closes docling-project#710
Signed-off-by: Eric Deandrea <eric.deandrea@ibm.com>
edeandrea
enabled auto-merge (squash)
September 29, 2026 20:56
:java_duke: JaCoCo coverage report
|
|
||||||||||||||
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
Ashfaqbs
added a commit
to Ashfaqbs/docling-java
that referenced
this pull request
Sep 30, 2026
A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after docling-project#711 and docling-project#714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with docling-project#714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com>
edeandrea
pushed a commit
to Ashfaqbs/docling-java
that referenced
this pull request
Oct 1, 2026
A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after docling-project#711 and docling-project#714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with docling-project#714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com>
edeandrea
pushed a commit
to Ashfaqbs/docling-java
that referenced
this pull request
Oct 1, 2026
A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after docling-project#711 and docling-project#714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with docling-project#714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com>
edeandrea
pushed a commit
to Ashfaqbs/docling-java
that referenced
this pull request
Oct 2, 2026
A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after docling-project#711 and docling-project#714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with docling-project#714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com>
edeandrea
pushed a commit
to Ashfaqbs/docling-java
that referenced
this pull request
Oct 5, 2026
A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after docling-project#711 and docling-project#714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with docling-project#714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com>
edeandrea
pushed a commit
that referenced
this pull request
Oct 5, 2026
* fix(client): keep status and body when a 422 is not a validation error A 422 whose body cannot be parsed as a validation error (for example an HTML page from a gateway) surfaced as a raw Jackson parse exception and lost the status code and response body. Fall back to DoclingServeClientException, as for any other 4xx/5xx. Rebased onto main after #711 and #714: - Narrow the fallback catch to the new JsonReadException instead of a broad RuntimeException, so a failure that is not a parse failure (a broken custom deserializer) still propagates. - parseValidationError now returns Optional<ValidationError> instead of a @nullable, folded together with #714's no-details filter. - Move the standalone tests into AbstractDoclingServeClientTests' UnprocessableEntityResponseTests, so both Jackson backends run them, and add a case guarding the narrowed catch via a mixin-based failing deserializer for ValidationError. - Update serve-api.md and whats-new.md. Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com> * fix(client): use Optional map/orElseGet chain and guard null detail bodies Addresses edeandrea's remaining review notes on #704: getResponse now throws validationError.map(...).orElseGet(...) instead of isPresent()/ get(), parenthesizes the ternary condition, and computes body.toString() once as responseBody. Also adds "null" and {"detail":null} cases to jsonBodyWithoutValidationDetailsKeepsStatusAndBody, which guard the Optional.ofNullable in parseValidationError against regressing to an unnoticed NPE. Signed-off-by: Ashfaq <105435085+Ashfaqbs@users.noreply.github.com> --------- Signed-off-by: Ashfaqbs <105435085+Ashfaqbs@users.noreply.github.com> Signed-off-by: Ashfaq <105435085+Ashfaqbs@users.noreply.github.com>
Contributor
|
🎉 This issue has been resolved in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DoclingServeClient.getResponsetreated every422as a validation error.ValidationErroris deserialized leniently (unknown properties are ignored), so any JSON object without validation details, such as{},{"error":"gateway says no"}or{"detail":[]}, became aValidationErrorwith an emptyerrorDetailslist. The client then threw aValidationExceptionwith a blank message, and the response body was not available to the caller.A
ValidationErrorwithout details is now treated as "not a validation error", and the client throws the genericDoclingServeClientException, which carries the status code and the response body, like any other 4xx/5xx response. A422that carries validation details still throws aValidationException.Closes #710
Changes
DoclingServeClient.getResponse: filter out aValidationErrorwith no details and fall through toDoclingServeClientException.AbstractDoclingServeClientTests.UnprocessableEntityResponseTests(runs on both the Jackson 2 and Jackson 3 clients): a parameterized test for{"error":"..."},{}and{"detail":[]}, and a test that a body with details is still aValidationException. Removing the filter turns the three no-details cases red on both backends.serve-api.md("Validation errors") andwhats-new.md.Notes
{"detail": []}: it goes fromValidationExceptiontoDoclingServeClientException. I have not confirmed whether docling-serve can ever emit an emptydetaillist. An emptyValidationExceptionhas nothing to inspect and no message, while the generic exception keeps the status and the body, so I think this is the better result either way. Please push back if you know otherwise.parseValidationError. The filter is written inline here because that method does not exist onmain; whichever PR lands second has a small conflict to resolve in this block, and the filter then becomes a one-line.filter(...)on theOptional.{"detail":null}on a422throws aJsonReadException("errorDetails cannot be null") instead of falling back. That is a parse failure on the same path, so it fits better with fix(client): keep status and body when a 422 body is not JSON #704 or a follow-up. I have not checked Jackson 3.