Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve response message on DecodingException #18815

Closed
PyvesB opened this issue Oct 11, 2019 · 11 comments
Closed

Improve response message on DecodingException #18815

PyvesB opened this issue Oct 11, 2019 · 11 comments
Labels
status: superseded An issue that has been superseded by another theme: web-error-handling type: enhancement A general enhancement

Comments

@PyvesB
Copy link

PyvesB commented Oct 11, 2019

Affects: 5.2.0


Hello,

When a DecodingException is thrown from a reactive handler chain, it is mapped to a ServerWebInputException, with a generic Failed to read HTTP message reason:
https://github.com/spring-projects/spring-framework/blob/d1aee0e8691c41753621332ff69b17be3f7c8ba2/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java#L73

As a consequence, all bad request bodies are similar, regardless of what caused them in the first place:

{"timestamp":"2019-10-10T13:32:32.210+0000","path":"/some-path","status":400,"error":"Bad Request","message":"Failed to read HTTP message"}

The client is not provided with any helpful message indicating why the request was unsuccessful, it's not even clear that this was caused by a failure to decode the body in the first place.

For example, when using a AbstractJackson2Decoder, the DecodingException contains much more useful information, such as:

JSON decoding error: Missing required creator property 'xxxxxx'

Could such information be included as part of the Bad Request response?

Thanks for reading!

Pyves

@rstoyanchev rstoyanchev self-assigned this Oct 15, 2019
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Oct 30, 2019

On second thought, I wonder if this is the right place to fix this. The ServerWebInputException is created with the root cause, so it does contain the reason for the 400 error. The error message in the response body however is likely written by Spring Boot. There is nothing in the framework that writes error details to the response body.

Taking a look at DefaultErrorAttributes it does seem to write only the message of the top level exception. Is there some room for improvement there @bclozel to also write the cause, or is there a reason why the cause isn't included?

@bclozel
Copy link
Member

bclozel commented Oct 30, 2019

Spring Boot is providing configuration properties for writing the actual exception class (server.error.include-exception) and the full stacktrace (server.error.include-stacktrace). Spring Boot is currently unwrapping Servlet exceptions (for Servlet containers) and ResponseStatusException (including subclasses like ServerWebInputException), but we're only including that information with the exception and the stacktrace themselves.

I assume this is because we don't want to expose information about application internals by default, and we're leaving that choice to developers.

@PyvesB
Copy link
Author

PyvesB commented Oct 30, 2019

@rstoyanchev thanks for your answer! Those were some of my thoughts as well when browsing through the code. As far as I can tell, there are two main ways to improve this:

  • expanding the exception message in spring-framework.
  • including the cause message in the response body in spring-boot.

@bclozel
Copy link
Member

bclozel commented Oct 30, 2019

@PyvesB Are you sure you're using Spring Boot 2.2? The error message should include the requestId now and I'm not seeing that in your sample.

I'm wondering if including the cause by default would not leak important internal information about the application.

@PyvesB
Copy link
Author

PyvesB commented Oct 30, 2019

@bclozel at the time of opening the issue, Spring Boot 2.2 was not yet released. So I did check out in the latest milestone, but took an error message from our production servers. Here's what it looks like with the latest:

{"timestamp":"2019-10-30T09:20:45.988+0000","path":"/some-path","status":400,"error":"Bad Request","message":"Failed to read HTTP message","requestId":"bccb992f"}

Only server.error.include-stacktrace gives access to some of the missing information and contains JSON decoding error: Missing required creator property 'xxxxxx'. But that also comes with the entire stack trace, which creates a giant payload, is extremely noisy from the API user's point of view and does consequently disclose much more information about the application.

I think a middle ground has to be found, where the user is not confusingly in the dark ("Failed to read HTTP message"), but has some indication of why his request is invalid.

@bclozel bclozel transferred this issue from spring-projects/spring-framework Oct 30, 2019
@bclozel bclozel assigned bclozel and unassigned rstoyanchev Oct 30, 2019
@bclozel bclozel added the type: enhancement A general enhancement label Oct 30, 2019
@bclozel
Copy link
Member

bclozel commented Oct 30, 2019

I've transferred this on the Spring Boot tracker so we can consider an enhancement here.
A sensible middle-ground would be to add a "cause" attribute to the DefaultErrorAttributes (in both MVC and WebFlux).

@bclozel bclozel added the for: team-attention An issue we'd like other members of the team to review label Oct 30, 2019
@rstoyanchev
Copy link
Contributor

I'm wondering if including the cause by default would not leak important internal information about the application.

I think including the top level message isn't all that different from including the root cause message, and arguably both could have been included, but starting to do that at this stage is almost certainly going to cause a surprise somewhere. Having the option to enable that seems reasonable to me. It is already possible by including the full stack trace, so this would be a sort of in-between option.

@bclozel bclozel removed the for: team-attention An issue we'd like other members of the team to review label Oct 30, 2019
@bclozel
Copy link
Member

bclozel commented Oct 30, 2019

The Spring Boot team has been discussing this and we're not 100% sure yet about that change.
I'll implement the change locally and try it out with various exceptions (codecs, IO errors, etc) and see how things look like. This feature would be useful in that very case but we're not sure that:

  • it's useful in all cases as the "relevant" information might be in the middle of the exception hierarchy
  • it might expose too much information
  • it might not really help more because the error message might be very implementation specific

I'll report back here with my findings.

@rstoyanchev
Copy link
Contributor

Whatever sample cases you find, I'm sure some will look good and some less so. I don't know if that helps to decide. Either way Boot already allows getting this information through the full stacktrace but to go there is to get too much and too implementation specific.

To me this is more a question of how rather than if. It should be configurable somehow. It would feel odd if by contrast all exceptions had to be modified to ensure their top-level exception include messages from nested exceptions, when the exception already includes everything.

Perhaps instead of another attribute for the root cause, it could be a property that effectively says, include all messages, not just the top one.

@ahatzz11
Copy link

ahatzz11 commented Jan 6, 2022

Has anyone found a solution to this issue? I've started running into it and it is tough to debug bad requests with the default message, and the stack trace is annoyingly verbose for our frontend developers. A middle ground solution would be great.

@philwebb philwebb modified the milestones: 2.x, 3.x Aug 19, 2022
@bclozel
Copy link
Member

bclozel commented Jan 16, 2025

Closing as superseded, since Spring Framework now allows to customize this through ResponseEntityExceptionHandler: developers can extend this type and contribute it as bean, and customize a Problem Detail response to add the relevant information.

@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Jan 16, 2025
@bclozel bclozel removed their assignment Jan 16, 2025
@bclozel bclozel added the status: superseded An issue that has been superseded by another label Jan 16, 2025
@bclozel bclozel removed this from the 3.x milestone Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another theme: web-error-handling type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

6 participants