-
Notifications
You must be signed in to change notification settings - Fork 491
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
POC: custom error handlers #49
POC: custom error handlers #49
Conversation
@jargv What are you're thoughts on this? |
For adding custom fields to the errors I'd suggest creating a new error type that has What do you think? |
ec96144
to
6270227
Compare
@neelance I've made that change. What do you think? |
Yes, that's the direction I wanted to go. But I think we should only set |
So I wouldn't even change the signature of |
3dd6c84
to
24b2045
Compare
Ok, I made that change. What do you think? Thanks again for your help! |
r.addError(errors.Errorf("%s", err)) | ||
queryError := errors.Errorf("%s", err) | ||
queryError.ResolverError = err | ||
r.addError(queryError) | ||
addResult(f.Alias, nil) // TODO handle non-nil |
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.
This may be a discussion for another thread but shouldn't this be addResult(f.Alias, result)
if the handler was able to resolve a partial amount of data, shouldn't we still send that to client and allow them to figure out what to do with it?
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.
The spec says that null
should be returned on error: http://facebook.github.io/graphql/#sec-Errors-and-Non-Nullability
Actually the null
should even propagate to the parent if the current field has a non-null type. This is not yet implemented.
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.
Interesting. Ok! Thanks!
@@ -554,7 +557,9 @@ func (e *fieldExec) execField(ctx context.Context, r *request, f *query.Field, r | |||
result, err := e.execField2(spanCtx, r, f, resolver, span) | |||
|
|||
if err != nil { | |||
r.addError(errors.Errorf("%s", err)) | |||
queryError := errors.Errorf("%s", err) | |||
queryError.ResolverError = err |
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.
Nice and simple. ❤️
@@ -303,6 +303,9 @@ func (r *request) addError(err *errors.QueryError) { | |||
func (r *request) handlePanic() { | |||
if err := recover(); err != nil { | |||
execErr := errors.Errorf("graphql: panic occured: %v", err) | |||
if err, ok := err.(error); ok { | |||
execErr.ResolverError = err |
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.
Hmm, is there a good scenario on why we should set the field on a panic? A panic should always be an unexpected internal error, so there should be nothing to tell the user except "internal error".
Right now the error message includes the panic's error value, but eventually I want to change it to only say "internal error" and not leak internals. However right now I don't want to do that yet because there are still some graphql-go error conditions that cause a panic and they would be hard to understand if the message was omitted.
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.
My thought here is that this could help your use case of not leaking internals. The error message could say something like "internal error" but more information (not available to client) could be included on the ResolverError (maybe thats a bad name) which won't get sent to client because it wont be serialized to json.
Also, if something panics in a resolver, won't it eventually be caught by this func? I don't have a use case for this yet but I could see myself wanting to have access to the originating error?
I don't feel very strongly about this so if you'd like me to remove it then I will.
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.
If you want access to the originating error to extract information from it, then the error is not unexpected and thus it does not qualify for a panic, right? ;-)
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.
Thats true.
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.
Removed.
24b2045
to
ae8518b
Compare
I removed changes from the panic Handler. Are we good to merge now? |
Yes, we are! |
@nicksrandall Thanks for contributing! |
Is there an example for using this? |
Is there an example of how to use this? |
we should write some docs 📝 |
@DenisNeustroev in lieu of docs, do you have a minimal example? 🙇 |
@DenisNeustroev I explored all code and I can't find way to provide custom errors to client. 😕 |
This proof of concept will likely need changes before it can be merged but I hope it can serve as a starting point for a conversation around how we can elegantly handle errors in this library.
This change gives users an optional hook to handle errors. Access to this hook opens up the door for several use cases:
One benefit of this approach is that it is non-breaking. Users are able to "opt-in" when needed.