Python graphql exception handling: Is it expected to get errors array with 200 OK response?

6.9k Views Asked by At

According to the documentation in https://www.howtographql.com/graphql-python/6-error-handling/ I use raise GraphQLError to show errors in my Flask GraphQL app mutate functions, like this one:

import graphene
from graphql import GraphQLError

from ...extensions import db
from ...models import User as UserModel
from ..types import User as UserType

class Update(graphene.Mutation):
    class Input:
        id = graphene.ID(required=True)
        # phone = graphene.String()
        name = graphene.String(required=False, default_value=None)
        # active = graphene.Boolean()

    Output = UserType

    @staticmethod
    def mutate(root, info, **kwargs):
        user = graphene.Node.get_node_from_global_id(info, kwargs.pop('id'))
        # print(info.context)
        # if not user:
        raise GraphQLError('eeee')
        # user.update(**kwargs)
        # db.session.commit()

        return user

I'm expecting to get something like a 400 status code with graphql error json schema. But I get 200 and also the exception is printed in console with traceback. Am I doing something wrong here?

An error occurred while resolving field Mutation.updateUser
Traceback (most recent call last):
  File "/.local/share/virtualenvs/Server-CvYlbWSB/lib/python3.7/site-packages/graphql/execution/executor.py", line 447, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/.local/share/virtualenvs/Server-CvYlbWSB/lib/python3.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/application/schema/mutation/user.py", line 40, in mutate
    raise GraphQLError('eeee')
graphql.error.base.GraphQLError: eeee
Traceback (most recent call last):
  File "/.local/share/virtualenvs/Server-CvYlbWSB/lib/python3.7/site-packages/graphql/execution/executor.py", line 447, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "/.local/share/virtualenvs/Server-CvYlbWSB/lib/python3.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "/application/schema/mutation/user.py", line 40, in mutate
    raise GraphQLError('eeee')
graphql.error.located_error.GraphQLLocatedError: eeee

127.0.0.1 - - [17/Oct/2018 01:46:54] "POST /graphql? HTTP/1.1" 200 - 
1

There are 1 best solutions below

1
On

It seems to be intentional that the stack trace is shown. You can view the discussion on GitHub. Just in case the link dies, the basics of the discussion was that the graphql-core library would essentially eat all errors thrown by graphene and place them in the results.errors array without printing a stack trace to sys.stderr. Generally, this is unwanted behavior, and thus it seems like it was changed in a pull request.


If you still want to mimic that behavior, you can view this StackOverflow answer to get rid of the stack trace: You can turn off the traceback by limiting its depth. It should still show up in results.errors this way; however note that this still prints the error message on the console, but it won't print the stack trace.

If you want to completely get rid of the error and stack trace on the console (I don't recommend this), you will need to catch the exception somewhere in the app outside of the mutation resolver in order for the error to still show up in the results.errors array. For instance you can do this when the Flask app is initially run (although the scope may be too large in this case).

try:
    app = Flask(__name__)
except GraphQLError as gqle:
    pass # ignore the error
except OtherErrorYouManuallyCall as oeymc:
    pass 
# Any other error will be thrown and show the stack trace