Reputation: 2821
I'm trying to display a simple "Email and password do not match" error on a login form, but am having trouble and not sure if where I've gone wrong is on the server or in my React app. I thought I'd post here as I'm unsure which github repo would be appropriate. Here's the resolver on the server:
// Schema definition:
type Mutation {
loginViewer(credentials: AUTH_CREDENTIALS): SignInPayload!
}
type SignInPayload {
token: String
expires: Int
requiresReset: Boolean
}
// Mapping the mutation to the resolver:
Mutation: {
loginViewer: loginViewerMutation,
},
// Resolver:
const loginViewerMutation = async (obj, args) => {
const { credentials } = args
const user = await User.findOne({ email })
if (!user) throw new GraphQLError('Email and password do not match')
const matches = await user.comparePassword(password)
if (!matches) throw new GraphQLError('Email and password do not match')
return createJWT(user)
}
Then, the mutation as it's called within my Login component:
const mutation = gql`
mutation LoginViewer($password: String!, $email: String!) {
loginViewer(credentials: { email: $email, password: $password }) {
token
expires
requiresReset
}
}
`
export class Login extends React.Component {
handleLogin = (credentials) => {
this.props
.mutate({ variables: { ...credentials } })
.then(() => {
// ...
})
.catch((error) => {
console.log(error.message)
console.log(error.graphQLErrors)
// ...
})
}
render() {
// ...
}
}
export default graqphql(mutation)(Login)
Everything works as expected when I supply the correct information. When I don't, the error that is caught doesn't contain the GraphQLErrors.
I'm using the apollo-link-error middleware with the default setup: https://www.apollographql.com/docs/link/links/error.html
My console looks like this:
The expected authentication error is being returned, and logged from the middleware. But, in my Login component, the error.graphQLErrors array is empty.
Where might I be going wrong here?
It doesn't seem right to be returning a 500 Internal Server Error --- it's behaving exactly as I want it to. Am I implementing this incorrectly on the server?
How are the graphQLErrors getting 'lost' between the logging middleware and the .catch(error)?
Upvotes: 1
Views: 1357
Reputation: 2821
I asked this question on the express-graphql github repo, they quickly pointed out that the solution was removing the !
on my loginViewer
mutation:
// Schema definition:
type Mutation {
loginViewer(credentials: AUTH_CREDENTIALS): SignInPayload!
}
// Should be:
type Mutation {
loginViewer(credentials: AUTH_CREDENTIALS): SignInPayload
}
It's expected behavior since your top-level field (loginViewer) defined as non-null. That means when error bubble up it GraphQL engine has no option except make data field equals to null:
Since Non-Null type fields cannot be null, field errors are propagated to be handled by the parent field. If the parent field may be null then it resolves to null, otherwise if it is a Non-Null type, the field error is further propagated to it’s parent field.
If all fields from the root of the request to the source of the error return Non-Null types, then the "data" entry in the response should be null.
http://facebook.github.io/graphql/draft/#sec-Errors-and-Non-Nullability
If data is null that means the entire request is failed and express-graphql response with 500.
Upvotes: 1