spring-boot-3.4.0

When I enable problem-details, the validation message of my parameters should be shown in the response. But it is still hidden. Example:

spring.mvc.problemdetails.enabled=true
spring.webflux.problemdetails.enabled=true
@RestController
public class DemoServlet {
    @GetMapping(value = "/info")
    public String bookinginfo(
            @RequestParam(name = "token")
            @Size(min = 3, message = "too short") String token) {
        return "ok";
    }

Result:

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "Validation failure",
    "instance": "/info"
}

Expected result: something like "token [size = 3] ... too short"... as hint for the client-user how he can fix his 400.

Comment From: bclozel

I think this behavior is implemented by Spring Framework in ResponseEntityExceptionHandler and it's not showing the validation message to avoid leaking information. Have you tried customizing the error message as explained in the reference documentation? Please let us know how this goes.

I'll transfer this issue there for further discussion.

Comment From: membersound

I think that should work out of the box, because the defaults for HandlerMethodValidationException.class are {0} list all validation errors.

Comment From: bclozel

I don't think Spring Framework ships with message sources by default. The reference doc mentions the Message Code Arguments that are available, not the default messages. Can you try and get back to us? Thanks!

Comment From: membersound

Here are my results, I tried all 3 variants:

problemDetail.org.springframework.web.method.annotation.HandlerMethodValidationException=validation errors: {0}

Result: the validation message is displayed, but the targeting parameter is missing completely:

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "validation errors: too short",   <---------- I would expect at least also the parameter names here
    "instance": "/info"
}

I also tried title and type message variants, which both produce results that I would not have expected:

problemDetail.title.org.springframework.web.method.annotation.HandlerMethodValidationException=validation errors: {0}

Result: title is taken plain, without replacing the {0} value:

{
    "type": "about:blank",
    "title": "validation errors: {0}",
    "status": 400,
    "detail": "Validation failure",
    "instance": "/info"
}
problemDetail.type.org.springframework.web.method.annotation.HandlerMethodValidationException=validation errors: {0}

Result: Exception on message rendering:

Caused by: java.net.URISyntaxException: Illegal character in scheme name at index 10: validation errors: {0}
    at java.base/java.net.URI$Parser.fail(URI.java:2995) ~[na:na]
    at java.base/java.net.URI$Parser.checkChars(URI.java:3166) ~[na:na]
    at java.base/java.net.URI$Parser.parse(URI.java:3192) ~[na:na]
    at java.base/java.net.URI.<init>(URI.java:645) ~[na:na]
    at java.base/java.net.URI.create(URI.java:930) ~[na:na]
    ... 68 common frames omitted

So, while the first message result improves the error message, I still think there is much room for improvement (at least including the parameter name that caused the error). Also I'm unsure if "type" and "title" behave as expected.

Comment From: quaff

I would expect at least also the parameter names here

@membersound You should try to use placeholder ${validatedValue} in your message, like this:

@Size(min = 3, message = "'${validatedValue}' is too short, length must be greater than or equal to {min}")

Comment From: rstoyanchev

We do not want to leak information, and also cannot easily format validation errors transparently because we have no knowledge of what's in the validation message, e.g. it could already have the parameter name, and likewise internationalization also requires customization. There are just too many variables to be able to provide something better out of the box, while keeping it customizable.

You have a few options.

Adding a problemDetail.org.springframework.web.method.annotation.HandlerMethodValidationException message property and using {0} to display all validation errors.

To customize the validation messages, you can set it on the annotation: @Size(min = 3, message = "Token must be greater than {min}")

You can also use your message.properties to customize validation messages as explained here. For example the following will customize all Size related errors across the application:

Size={0} must be > {2} and < {1}

There is also an option to handle HandlerMethodValidationException with a visitor that lets you handle validation errors by type of method parameter (request param, header, cookie, etc).

Comment From: rstoyanchev

Also I'm unsure if "type" and "title" behave as expected.

You can customize those, but there are no arguments, so leave out the {0}.