github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/docs/content/reference/errors.md (about) 1 --- 2 linkTitle: Handling Errors 3 title: Sending custom error data in the graphql response 4 description: Customising graphql error types to send custom error data back to the client using gqlgen. 5 menu: { main: { parent: 'reference', weight: 10 } } 6 --- 7 8 ## Returning errors 9 10 All resolvers simply return an error to be sent to the user. The assumption is that any error message returned 11 here is appropriate for end users. If certain messages aren't safe, customise the error presenter. 12 13 ### Multiple errors 14 15 To return multiple errors you can call the `graphql.Error` functions like so: 16 17 ```go 18 package foo 19 20 import ( 21 "context" 22 23 "github.com/vektah/gqlparser/v2/gqlerror" 24 "github.com/99designs/gqlgen/graphql" 25 ) 26 27 func (r Query) DoThings(ctx context.Context) (bool, error) { 28 // Print a formatted string 29 graphql.AddErrorf(ctx, "Error %d", 1) 30 31 // Pass an existing error out 32 graphql.AddError(ctx, gqlerror.Errorf("zzzzzt")) 33 34 // Or fully customize the error 35 graphql.AddError(ctx, &gqlerror.Error{ 36 Path: graphql.GetPath(ctx), 37 Message: "A descriptive error message", 38 Extensions: map[string]interface{}{ 39 "code": "10-4", 40 }, 41 }) 42 43 // And you can still return an error if you need 44 return false, gqlerror.Errorf("BOOM! Headshot") 45 } 46 ``` 47 48 They will be returned in the same order in the response, eg: 49 ```json 50 { 51 "data": { 52 "todo": null 53 }, 54 "errors": [ 55 { "message": "Error 1", "path": [ "todo" ] }, 56 { "message": "zzzzzt", "path": [ "todo" ] }, 57 { "message": "A descriptive error message", "path": [ "todo" ], "extensions": { "code": "10-4" } }, 58 { "message": "BOOM! Headshot", "path": [ "todo" ] } 59 ] 60 } 61 ``` 62 63 ## Hooks 64 65 ### The error presenter 66 67 All `errors` returned by resolvers, or from validation, pass through a hook before being displayed to the user. 68 This hook gives you the ability to customise errors however makes sense in your app. 69 70 The default error presenter will capture the resolver path and use the Error() message in the response. 71 72 You change this when creating the server: 73 ```go 74 package bar 75 76 import ( 77 "context" 78 "errors" 79 80 "github.com/vektah/gqlparser/v2/gqlerror" 81 "github.com/99designs/gqlgen/graphql" 82 "github.com/99designs/gqlgen/graphql/handler" 83 ) 84 85 func main() { 86 server := handler.NewDefaultServer(MakeExecutableSchema(resolvers)) 87 server.SetErrorPresenter(func(ctx context.Context, e error) *gqlerror.Error { 88 err := graphql.DefaultErrorPresenter(ctx, e) 89 90 var myErr *MyError 91 if errors.As(e, &myErr) { 92 err.Message = "Eeek!" 93 } 94 95 return err 96 }) 97 } 98 99 ``` 100 101 This function will be called with the same resolver context that generated it, so you can extract the 102 current resolver path and whatever other state you might want to notify the client about. 103 104 105 ### The panic handler 106 107 There is also a panic handler, called whenever a panic happens to gracefully return a message to the user before 108 stopping parsing. This is a good spot to notify your bug tracker and send a custom message to the user. Any errors 109 returned from here will also go through the error presenter. 110 111 You change this when creating the server: 112 ```go 113 server := handler.NewDefaultServer(MakeExecutableSchema(resolvers) 114 server.SetRecoverFunc(func(ctx context.Context, err interface{}) error { 115 // notify bug tracker... 116 117 return errors.New("Internal server error!") 118 }) 119 ``` 120