Repository navigation
Conversation
618755c to
ce1b74f
Compare
:java_duke: JaCoCo coverage report
|
|
||||||||||||||
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
ce1b74f to
7e70f96
Compare
edeandrea
left a comment
There was a problem hiding this comment.
Thanks for the PR, @Ashfaqbs. Falling back to DoclingServeClientException (status and body kept) when a 422 isn't a validation error is the right behavior. I tried it on both Jackson backends: an HTML page, [1, 2], an empty body and null all end up as a DoclingServeClientException with status 422 and the original body, while a real validation body still throws ValidationException.
A few things I'd like to see before this merges (details inline):
- Narrow the catch to
JsonReadException. This relies on #711, which came out of my review of this PR. See the inline comment. - Move the tests into
AbstractDoclingServeClientTestsso both Jackson backends run them, and add a case for the narrowed catch (inline). - (non-blocking) Return
OptionalfromparseValidationErrorinstead of@Nullable(inline). - Docs.
docs/src/doc/docs/docling-serve/serve-api.md("Validation errors") says a422from docling-serve makes the API throwValidationException. With this change that is only true when the body can be read as a validation error. Otherwise it is aDoclingServeClientExceptioncarrying the status code and body. Could you add a sentence there, and a bug-fix bullet under the current version indocs/src/doc/docs/whats-new.mdnext to the entry from #711?
One thing that is not needed here: a JSON 422 body with no detail (for example {"error": "..."}) still parses into an empty ValidationError and gives a ValidationException with a blank message. That is pre-existing and separate from what this PR fixes, so I opened #710 for it.
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
7e70f96 to
9a9707f
Compare
|
Thanks for the thorough review, @edeandrea. Rebased onto main (picked up #711 and #714) and addressed all four points:
Since #714 landed first and already added the no-details filter inline, I merged that filter into
|
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
There was a problem hiding this comment.
Thanks for the quick turnaround, @Ashfaqbs, and for folding #714's filter into parseValidationError instead of keeping two checks. All four points from the last round are in: the narrowed JsonReadException catch, the Optional return, the tests in AbstractDoclingServeClientTests (with a working mixin hook for the propagation case), and the docs. I ran the new tests on both Jackson backends and checked that they can fail: widening the catch, making it never fire, and dropping the empty-details filter each turn them red. I've resolved the three earlier threads.
What is left is small, and none of it blocks the merge:
getResponsestyle (inline).isPresent()followed byget()should be a fluentOptionalchain, and the condition of the inline conditional needs parentheses. One suggestion covers both.nullbodies (inline). Nothing guardsOptional.ofNullable, and{"detail":null}is worth a case.- The PR description still describes the first version of this change: it mentions
DoclingServeClientErrorResponseTests, "no container needed", and "if the 422 body cannot be parsed". Could you update it to match what the PR does now? The catch namesJsonReadException(added by #711), the tests are inUnprocessableEntityResponseTestsand run through Testcontainers, and the no-details filter from #714 now lives inparseValidationError.
Once these are in, this looks good to me.
6d377fd to
b8e0a71
Compare
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
b8e0a71 to
2e7612b
Compare
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
…odies Addresses edeandrea's remaining review notes on docling-project#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>
|
Thanks for the two follow-up notes. Pushed both:
|
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
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>
…odies Addresses edeandrea's remaining review notes on docling-project#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>
57931e3 to
4aedc5b
Compare
edeandrea
left a comment
There was a problem hiding this comment.
Thanks a lot, @Ashfaqbs, for sticking with this through several rounds, including one request that depended on #711, which didn't exist when you opened the PR. Folding #714's no-details filter into parseValidationError rather than keeping two checks was a good call, and the mixin-based failing deserializer for the propagation test was exactly right.
I re-ran everything on top of your branch. The 422 and non-JSON tests pass on both Jackson backends, and each guard is real: widening the catch, replacing Optional.ofNullable with Optional.of, an always-true filter and a wrong status code each turn tests red. I also updated the PR title and description to match what the PR does now.
Approving. Thanks again!
|
HTML test reports are available as workflow artifacts (zipped HTML). • Download: Artifacts for this run |
|
🎉 This issue has been resolved in |
What
DoclingServeClient.getResponseread every422body as aValidationError. A422that does not come from docling-serve (for example an HTML or plain-text error page from a gateway or proxy) madereadValuethrow, so the caller got a raw parse failure and the status code and response body were lost.Change
parseValidationErrornow catchesJsonReadException(added in fix(client): log a non-JSON response body as it is #711), whichreadValuethrows when the body is not valid JSON or does not match the expected type. In that case the client falls back to aDoclingServeClientExceptioncarrying the status code and the response body, like any other error response. Any other failure, such as a broken custom deserializer, still propagates.parseValidationErrorreturnsOptional<ValidationError>, and fix(client): throw DoclingServeClientException for a 422 without validation details #714's no-details filter moved into it, so there is a single check. A422is aValidationExceptiononly when it carries validation details. A body that is not JSON, JSON of another shape,null, or JSON without details is aDoclingServeClientException.getResponsethrows the result ofmap(...).orElseGet(...)on thatOptional.serve-api.md("Validation errors") andwhats-new.md.Tests
The cases are in
UnprocessableEntityResponseTestsinAbstractDoclingServeClientTests, so they run against both the Jackson 2 and the Jackson 3 client:422with validation details is aValidationException422whose JSON body has no validation details ({"error": ...},{},{"detail":[]},null,{"detail":null}) is aDoclingServeClientExceptionwith the status code and body422with an HTML body is aDoclingServeClientExceptionwith the status code and bodyJsonReadExceptionpropagates, through a client whose mapper fails onValidationError(via a mixin)Signed off per DCO.