Skip to content

422 with a JSON body that has no validation details throws ValidationException with a blank message #710

Closed

Description

@edeandrea

Summary

DoclingServeClient.getResponse treats every 422 as a validation error. If the body is a JSON object that has no validation details, it still throws a ValidationException, with an empty ValidationError and a blank error text, and the original response body is not available to the caller.

Reproduction

Tested on main (174a56e) with a WireMock stub for GET /health returning 422 with Content-Type: application/json, on both DoclingServeJackson2Client and DoclingServeJackson3Client (prettyPrint() off):

Body Result
{"error":"gateway says no"} ValidationException, message ends with ...request to <url>: followed by nothing
{} same
{"detail":[]} same

Cause

ValidationError deserialization is lenient: unknown properties are ignored on both Jackson 2 (FAIL_ON_UNKNOWN_PROPERTIES is disabled on the client's mapper) and Jackson 3. Any JSON object therefore deserializes successfully into a ValidationError whose errorDetails list is empty, so no parse failure ever signals "this is not a validation error".

Suggested change

Treat a ValidationError with no details as "not a validation error" and fall back to the generic DoclingServeClientException, which carries the status code and the response body, like any other 4xx/5xx response. In parseValidationError, after the JsonReadException catch that #704 introduces (see below), that is one more step on the Optional:

return Optional.ofNullable(readValue(body, ValidationError.class))
    .filter(error -> !error.getErrorDetails().isEmpty());

Notes

  • This is a behavior change for {"detail": []}: it would go from ValidationException to DoclingServeClientException. I have not checked whether docling-serve can ever emit an empty detail list; that should be confirmed before deciding.
  • It touches the same code as fix(client): keep status and body when a 422 body is not JSON #704, which adds a fallback for a 422 body that cannot be parsed at all (for example an HTML page from a gateway). I'd suggest landing this after fix(client): keep status and body when a 422 body is not JSON #704, since that PR restructures parseValidationError, and the filter then becomes a one-line addition.
  • A regression test needs a JSON body without detail on both backends, in AbstractDoclingServeClientTests. It only needs plain WireMock bodies, so the normal getDoclingClient(false, true) client is enough; it does not need the failing-deserializer client. Removing the filter should turn it red on both.
  • Jackson 2 and Jackson 3 currently disagree on {"detail":"plain string"} (Jackson 2 gives a ValidationException, Jackson 3 a DoclingServeClientException). That is a separate inconsistency, so keep it out of shared assertions.

Related

Activity

  1. added a commit that references this issue on Sep 29, 2026
    8b77e2a
  2. docling-java-ops commented on Oct 5, 2026

    @docling-java-ops
    Contributor

    🎉 This issue has been resolved in v0.7.0 (Release Notes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmodule:docling-serve-clientThe docling-serve-client modulereleasedIssue has been released

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions