Scot Matson
Scot Matson

Reputation: 745

How to capture the GraphQL error message in Relay?

On my server, my implementation of GraphQL is using Flask, Graphene, and SQLAlchemy. Ideally I would like to be able to simply manipulate the headers and return a 401 error response, but GraphQL returns everything as 200.

Using flask.abort(401) however I am at least able to obtain this response:

...
"errors": [
  {
    "message": "401 Unauthorized: The server could not verify that you are authorized to access the URL requested.  You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.",
    "locations": [
      {
      "line": 11,
      "column": 3
      }
    ]
  }
]
...

I see this as a compromise that I can work with at this point in time. However; because nothing can just be that simple... I am not sure as to how I can grab this error message. I've read that there might an issue with the QueryRenderer itself that swallows these GraphQL errors but I can manage to intercept them in the Network object in the Environment... that essentially looks something like this.

Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: {…}}
  __proto__: Promise[
    [PromiseStatus]]: "resolved"
    [[PromiseValue]]: Object
      data: {viewer: {…}}
      errors: Array(4)
        0: {locations: Array(1), message: "401 Unauthorized: The server could not verify that…nderstand how to supply the credentials required."}
        1: {locations: Array(1), message: "401 Unauthorized: The server could not verify that…nderstand how to supply the credentials required."}
        2: {locations: Array(1), message: "401 Unauthorized: The server could not verify that…nderstand how to supply the credentials required."}
        3: {locations: Array(1), message: "401 Unauthorized: The server could not verify that…nderstand how to supply the credentials required."}
      length: 4
      __proto__: Array(0)
    __proto__:Object

I don't really feel like handling this error at the Network layer of my Environment would be the proper way to manage this. The QueryRenderer seems to make the most sense... I have set it up essentially as the single source of truth.

I am using Relay Modern by the way if that wasn't obvious. So more likely than not any solutions based around Relay Classic will not apply.

Edit: Error message aside, my motivation for this was proper handling of JWT tokens. I think the solution I am looking for isn't related to handling these error responses but rather expanding my understanding of JWT.

I didn't realize that my client would easily be able to decode the JWT using a package such as the jwt-decode which then gives me access to expiration information... which ultimately I foresee leading me to some form of middleware implementation that would assess the amount of time remaining on the JWT and if a refresh is necessary.

Upvotes: 1

Views: 4694

Answers (3)

Omkar Rajam
Omkar Rajam

Reputation: 791

In environment.js, modify fetch function such that if errors array exists in JSON response, you will throw it as a new custom error. This thrown error will get transmitted to QueryRenderer where it will be available as error prop. Handle it there, by showing error related UI if an error is present.

See this comment on GitHub for detailed explanation: https://github.com/facebook/relay/issues/1913#issuecomment-470541691

Upvotes: 2

liminal18
liminal18

Reputation: 563

I hope I am understanding your question correctly, bit your QueryRenderer should have an error object that conains the error https://facebook.github.io/relay/docs/query-renderer.html

render={({error, props}) => {
if (error) {
  return <div>{error.message}</div>;
} else if (props) {
  return <div>{props.page.name} is great!</div>;
}
return <div>Loading</div>;

Upvotes: 1

tkymtk
tkymtk

Reputation: 2705

You can handle server errros in the onCompleted callback: https://github.com/facebook/relay/pull/1938/files

Upvotes: 1

Related Questions