-
-
Notifications
You must be signed in to change notification settings - Fork 140
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
Fix TypeError while sorting errors in build_response #68
Fix TypeError while sorting errors in build_response #68
Conversation
As GraphQLError objects might have 'None' as value for their 'locations' and 'path' attributes, a check must be placed in order to avoid raising a TypeError inside the errors list's 'sort' method. This commit changes None by an empty list to enable proper pairwise comparisons.
First of all, thank you very much for this project! It is very fortunate for the Python community to count with such a complete implementation of the GraphQL specification. Regarding this Pull request, I want to clarify that I couldn't manage to create a test to reproduce exactly what is happening to me in my production environment. However, as you can see, the proposed change doesn't invalidate any of the current tests. What I'm experiencing, albeit randomly, is the following unhandled error:
To understand what was happening, I put the following code inside the ExecutionContext.build_response method just before the errors sorting: def build_response(
self, data: AwaitableOrValue[Optional[Dict[str, Any]]]
) -> AwaitableOrValue[ExecutionResult]:
...
for i, error in enumerate(errors): # Display Error Attributes
print(f'<{i}> L: {error.locations} - P: {error.path} - M: {error.message}')
errors.sort(key=lambda error: (error.locations, error.path, error.message))
return ExecutionResult(data, errors) And what I'm getting in the console is the following:
As you can see in line: By adding the "or []" check, we prevent such eventual unhandled errors. |
Thank you for reporting this and the suggested fix, @tebanep. I'd like to add a regression test, but currently cannot come up with a test case where located and non-located errors are output simultaneously. Can you find which kind of error was output as <8>? I also wonder why "M" is always empty in your output. There should actually be a message, and it should give us a clue how we could create a test case. Also, theoretically even with the fix there could still be a problem since "path" contains mixed int and str values. Though it's even harder for me to think of an example where the paths are incompatible but the locations are equal. Anyway, maybe it's better to remove the path from the key, and just add id(error) as the last element in the key to make it deterministic? |
Hello @Cito. Thanks for your fast response. As I mentioned it, I have not been able to reproduce the problem with a test, for that I think I'll need a deeper undestanding of this project. However, while working with the graphql playground and repeatedly pressing the "play" button, I randomly get the error at issue. I'll use a debugger to dig deeper in the code and find the possible cause of the problem. Nevertheless, don't you think some kind of validation should be placed in the errors sorting key since some of their attributes are declared as "optional" and might eventually have "None" values? By the way, I also think that a simpler key to sort the errors would be preferable. |
I will also check why the messages are not being assigned to the created error instances. As you said, that might give us a clue. |
Sure, that definitely needs to be fixed before the final release and I'm glad you brought it up. I just wanted to create a test case that produces both located and non-located errors, so if you find how you managed to get these, let me know :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this a bit more. Actually, the fact that path
is mixed int and str is not problematic. While it can happen that int and str appear at the same position in two paths, it cannot happen that the first elements of two paths are the same and the next one has a different type, which is the only problematic case for sorting. So path or []
should be safe as sort key. Also, my idea to add id(error)
seems not to make sense any more on second thought, since the id depends on the order in which the errors are generated, which is the very thing we want to fix by sorting. So in short, I think your original suggestion seems to be the best fix to me.
If you find a way to reproduce the error, let me know, so that we can add a regression test.
Thanks a lot for integrating this fix, @Cito! As I told you, I will try to find the source of the problem to build a regression test. Let's see how it goes. Have a great day! |
As GraphQLError objects might have 'None' as value for their 'locations' and 'path' attributes, a check must be placed in order to avoid raising a TypeError inside the errors list's 'sort' method. This commit changes None by an empty list to enable proper pairwise comparisons.