strawberry-graphql / strawberry-django

Strawberry GraphQL Django extension
MIT License
391 stars 115 forks source link

Raising django.core.exceptions.ValidationError in strawberry_django.mutations.fields.DjangoUpdateMutation/DjangoCreateMutation/DjangoDeleteMutation.resolver fails #542

Closed Elawphant closed 3 weeks ago

Elawphant commented 3 weeks ago

When I try to raise django.core.exceptions.ValidationError in strawberry_django.mutations.fields.DjangoUpdateMutation/DjangoCreateMutation/DjangoDeleteMutation.resolver, it fails. The result is an empty json without errors and data.

I believe this is a bug with handle_django_errors or is specifically related to django.core.exceptions.ValidationError, because raising an ordinary python Exception outputs the error.

Upvote & Fund

Fund with Polar

bellini666 commented 3 weeks ago

Hey @Elawphant ,

That's the expected behaviour. When you use handle_django_errors=True, the resolver will intercept any ValidationError/PermissionDenied/DoesNotExist issues and return them as an OperationInfo object: https://strawberry-graphql.github.io/strawberry-django/guide/mutations/#django-errors-handling

When requesting the data, you can get the error like this:

mutation {
  someMutation(...) {
    ... on ExpectedType {
      id
      ...
    } 
    ... on OperationInfo {
      messages {
        kind
        message
        field
        code
      }
    }
  }
}
Elawphant commented 3 weeks ago

@bellini666 I see now! Will setting it to false combine them into GQL field errors? If so, I wonder which approach is more widespread ?

bellini666 commented 3 weeks ago

@Elawphant setting to False will make them fail just like any other exception.

The idea behind that option is to handle those errors as "expected", and return something that the client can use to highlight the errors to the user. e.g. "The field foo cannot be blank". Just like what is described in https://strawberry.rocks/docs/guides/errors#expected-errors

Django admin itself does when you try to save something that fails its validation.

Regarding the more widespread, I don't actually know. I know that I always set it to True as it makes sense IMO, but other users usage may vary a lot

Elawphant commented 3 weeks ago

I have made the default handle_django_errors to default unset (False). A pole in GQL Discord pointed that devs are more inclined to having errors in single place. Also, since settings can have global handle_django_errors option, the dev can easier configure own preference. Thanks for the help!

bellini666 commented 3 weeks ago

Awesome!

Going to close this as it seems to be solved. But tell me if that's not the case so we can reopen this