-
-
Notifications
You must be signed in to change notification settings - Fork 874
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
Error handling with 3.2 is inconsistent & difficult #5963
Comments
#4997 is related. It got auto close unfortunately :( |
I really need to document this better as you don't need so much complexity. For now you can disable the feature
Because you can't create an exception from another exception, the trace will be replaced by PHP.
IMHO it should be internal, I really got submerged with a bit too much work (especially working on #5882) and I should've spent more time into documenting this. My idea was that you should be able to own your exceptions and as these can be resources you can put everything you need without having to add normalizers (which are a pain). Maybe that you can help me document this and see if something like this works (I don't have much time to try this out until next week).
Let's help each others implementing this, I wish this was a little more mature and the whole work behind errors was meant to fix issues like #4997 not make things more complicated... |
Thanks Antoine for your detailed answer! I could help with documenting this, but first I need to fully understand this.
This does not help, because even then Symfony's ProblemNormalizer is called:
I'm not sure if this is because of another configuration that should be changed. But actually I think it is a good thing to have this new standards compliant responses. But for all the existing clients to our API there should be no b/c break, because they all check for 'hydra:description', which currently is not present for routing errors (see #5961). And this ProblemNormalizer creates the rfc_7807 JSON structure (but without the problem content-type header) that is later not decorated with the required Hydra props.
Yes, creating a new ApiResource\Error creates a new internal trace, but we are talking about the originalTrace which is already supplied to the constructor as array. So it could hold any arbitrary content already + the property is not overwritten from the base \Exception, what prevents making the property private and adding getters/setters?
It seems we misunderstand each other here: We do not want to modify the result just for some special endpoint/use case/exception. But (be able to) translate all error messages, regardless of source & type. Please see my example for reference. E.g. we translate symfony's "Invalid credentials." from BadCredentialsException to a parseable string as well as generic validation errors or custom exception messages.
As above: I don't think that solves the problem. The main problem imho is, that currently not all errors that can occur are transformed to an ApiResource\Error which is then appropriatly handled / decorated with Hydra props / sent with the problem header by ApiPlatform. But that some (routing & auth) errors go through symfony's own error handling/serialization.
Probably this should be a new functionality in ApiPlatform: Intercept all errors thrown in Symfony (404, 405 from routing problems; 400, 401 from auth problems etc) and feed them into APIP's processor chain. [Update:] Sure, APIP should not impose itself on other parts of the application that handle other routes. But that's difficult to decide: Currently, the ExceptionListener logic also decides that calling an APIP endpoint with the wrong HTTP method is not handled, which is (for me atleast) an unpreferable result. This also causes the problem detailed in #4997 as authentication routes - by lexikJwt or other auth systems - are exempt. But this also has two sides: LexikJwt answers in application/json for success responses and authentication errors per default. Simply disabling the check in the ExceptionListener only causes "error 400" responses (because of missing credentials) to be enhanced as Hydra responses, not all (success or error) responses. I tried simply disabling the route check in the ExceptionListener, this already helped so far as 405 errors get the correct Hydra response. But they still don't get the problem content-header. Also, my problem with the ApiResource\Error itself would go away if there was a way to intercept APIP's serialization process of it. But currently the |
We really need a way to preserve old behavior (before 3.2). API is used by frontend client, which relays on specific error format (hydra:description, etc) Currently both config options: |
Hi everyone sorry really got caught up but we have lots of issues with errors right now so tomorrow I'll provide the In the meantime you can override our ErrorListener service with something like:
But I'd recommend to stay on 3.1 while I provide a proper fix. Thank you for your patience! |
Please update to 3.2.5 and use I also found a way to make |
Not trying to complain too much for such an awesome platform given to us for free but really the latest error changes are a mess, especially because they are too complex to understand and not really well documented. For example the latest update from 3.2.4 to 3.2.5 broke all of our tests because validation errors did not contain a api_platform:
defaults:
extra_properties:
rfc_7807_compliant_errors: true So we need to enable the RFC7807 errors to restore the |
Indeed I'm reproducing that I tested manually I will add this to the test matrix! |
Can someone try #5974 for the bc layer? I still need a bit more time to add this to our test suite but it looks promising with manual tests. |
A very quick (!) test fixes the default behavior for me. Just tested a simple 404 to a non-existant route. |
well it took quite some time but I'm close to something better which handles a proper bc layer and also makes that 3.2 system actually usable (it's not if you can't customize exceptions). It should be out soon I need to try a few more things manually. In my patch I reverted everything to the previous error handling when the flag is Really sorry for the delay, I had to work (a lot) on the documentation as we had issues using Next.js and therefore we couldn't update the documentation pages. By the end of the week there will be a proper documentation page to help with the new Error stuff. Stay tuned! |
So, tried "update to 3.2.5 and use rfc_7807_compliant_errors: false": BEFORE 3.2.x: Lets take login 401 error (APP_DEBUG=false):
WITH 3.2.5 and rfc_7807_compliant_errors: false:
So completely different result and even error response "The presented password is invalid" is removed. WITH 3.2.5 and rfc_7807_complient_errors: true:
better, but frontend client needs rewrite. |
WITH "api-platform/core": "dev-error-bc as 3.2.5", and, DEBUG=false, and rfc_7807_compliant_errors: false:
So detail message is back, but hydra attributes missing. |
yes What is the Having APP_ENV=dev: APP_ENV=prod: |
Ok, I see! Now I have two options: Other option is to add config:
so that other two choices (jsonproblem, jsonapi) are removed. Thanks! Hope this fixes BC issues for me and others and you can move forward with new error handling & docs. |
okay so I'll set error_formats with jsonld first it should do the trick, thanks! /edit I'm no sure that this is best though I think we should stick with problem+json when we're not sure of the content type required. |
I mean, before 3.2.x jsonld was the default error format, it seems.
|
I managed to finish today please read #5974 and let me know if there's something not understandable. You can also try this patch although it'll be released tomorrow with its documentation. |
I've released my patch, please let me know if things are not working with
|
Sorry, was caught up in other projects, came back to testing now.
Yes it does break, it does not work as I expected: 3.2.4 + 3.2.5 worked so far as Symfony-triggered errors (No route found...) returned a Problem response (with Same config for all tests:
|
Mhh but https://github.com/api-platform/core/blob/main/features/hydra/error.feature#L57-L70 @j-schumann can you tell me how to reproduce? |
The Test you linked tests only an exception that is triggered by ApiPlatform, not an exception from the Symfony routing. I would expect all those tests I added to pass: main...j-schumann:api-core:main For the JSON-API tests: I'm not familiar with it, but imho either the description or the expectation does not match: For a response to be a rfc 7807 response, the type/title/detail props must be in the root of the response JSON, not encapsulated with a |
nice thanks! I'll check the spec on jsonapi it should indeed be at the root of the JSON (https://jsonapi.org/format/#error-objects) |
I'm not 100% on this one. While RFC 7807 Appendix B and RFC 9457 Appendix C state, that problem details can be embeded in other formats, RFC 9457 Section 3 (which superceedes 7807) clarifies how multiple errors should be returned:
|
Actually reading the spec again none of the fields are mandatory, and having the errors inside the I also have a problem with
as we don't handle symfony errors. I've attached a feature that would solve your issues, as this was not supported in 2.7 nor 3.x we need to introduce this as a new feature. |
OK, that settles the JSON API responses.
But API Platform handled those errors in 2.x and that wasn't deprecated/documented as "breaking change" in 3.0. Also, as I wrote in #5961, AP 3.1.x handled Symfony errors. |
No the test you send me on the 404 (And I send a "POST" request to "/does_not_exist" with body:) doesn't work on the 3.1 branch. I'll settle to merge my fix but you'll need to bypass the symfony errors with the configuration flag. The one on |
I know, I wondered how that is. Because for all my AP projects this worked / still works with the correct versions. Maybe there are differences in how the project is configured for the tests, but I don't have any special code/config implemented to explicitly make this work. There is a very simple test to verify:
and:
For me that looks like API Platform handled those errors and produced a correct Hydra response. |
Demo works on current 3.2, I think that the test issue is that it doesn't specify any |
Exactly, and that shows two things:
|
My bad, demo works on 3.1 ^^. I'm trying another approach at #6056 |
v3.2.8 solves the latest reported issues. |
Description
With 3.2 there are two different ways in which error responses are created:
ProblemNormalizer
is used.ApiResource\Error
is created and serialized. (At least when using no deprecated features / the new problem responses)This leads to multiple problems:
ApiResource\Error
error before it is serializedApiResource\Error
is immutable, which requires us to create a new instance to modify a single value, e.g. the 'detail'->with...()
clone methods like most of theApiPlatform\OpenApi\Model
classes have (withParameters, withTrace, withDescription, ...)? Also theORM|ODM|ElasticSearch\State\Options
or the MetaData class(es) have them.The feature request would be to simplify the modification of the error results, for all error sources together and to better document how this can be done. Currently the docs (https://api-platform.com/docs/core/errors/) neither shows how to use a Provider nor a Serializer to modify the response, and it does not mention the (current) differences in error handling & output.
Example
We want to translate the error messages generated by Symfony's routing / Lexik JWT / Validators / custom exceptions to be parseable by the API-Client.
Currently we have to use:
and
which also causes the Error constructor to iterate over the whole stacktrace again to remove the (already removed) args. (yes, we could first provide an empty array as trace and later simply set $data->originalTrace, see below)
Additional context
Additional questions / feedback
originalTrace
public inApiResource\Error
? What was the reason to not use a getter like with all other properties and an additional setter?The text was updated successfully, but these errors were encountered: