Graphql-yoga: Custom error

Created on 14 Feb 2018  路  17Comments  路  Source: dotansimha/graphql-yoga

Is it possible to throw custom Errors? I have defined a custom Error class, but none of the additional fields are being sent with the error response.

kinquestion statupr-welcome

Most helpful comment

@schickling sure!
server-side:

// really basic custom error and auth resolver
type ErrorValues = { email?: string; password?: string };

class AuthError extends Error {
  public errorValues: ErrorValues;

  constructor(values: ErrorValues) {
    super();
    Object.setPrototypeOf(this, AuthError.prototype);
    this.errorValues = values;
  }
}

export const authResolvers = {
  async login(parent, { email, password }, ctx: Context, info) {
    const user = await ctx.db.query.user({ where: { email } });
    if (!user) {
      throw new AuthError({ email: Errors.LOGIN_EMAIL });
    }

    const valid = await compare(password, user.password);
    if (!valid) {
      throw new AuthError({ password: Errors.LOGIN_PASSWORD });
    }

    return {
      token: sign({ userId: user.id }, process.env.APP_SECRET),
      user
    };
  }
};

then on the client-side:

// using apollo-client
const LOGIN_MUTATION = gql`
  mutation Login($email: String!, $password: String!) {
    login(email: $email, password: $password) {
      token
    }
  }
`;
// ... standard sorta login component
  private onSubmit = async (variables: FormValues, { setErrors }: FormikProps<FormValues>) => {
    const { history, mutate } = this.props;
    try {
      const result = await mutate({
        variables
      });
      const { data: { login: { token } } } = result;
      login(token);
      history.replace('/');
    } catch (error) {
      console.log(error); // <-- right here it would be nice to be able to access custom AuthError values
    }
  };

I know there are a few ways for that error to show up and apollo-client ApolloError gives you an array of GraphqlError objects (which aren't Error objects, but formatted custom Objects). But somewhere nested in that ApolloError it'd be nice to be able to access AuthError.errorValues from the server, but it looks like those values are stripped before the error is sent in the response. Let me know if I am missing anything useful from the example, I was trying to keep it minimal.

All 17 comments

Can you describe your desired behaviour a bit more in detail by (1) showing the client code you'd like to use and (2) the GraphQL error response you'd like to see from a client's perspective?

@schickling sure!
server-side:

// really basic custom error and auth resolver
type ErrorValues = { email?: string; password?: string };

class AuthError extends Error {
  public errorValues: ErrorValues;

  constructor(values: ErrorValues) {
    super();
    Object.setPrototypeOf(this, AuthError.prototype);
    this.errorValues = values;
  }
}

export const authResolvers = {
  async login(parent, { email, password }, ctx: Context, info) {
    const user = await ctx.db.query.user({ where: { email } });
    if (!user) {
      throw new AuthError({ email: Errors.LOGIN_EMAIL });
    }

    const valid = await compare(password, user.password);
    if (!valid) {
      throw new AuthError({ password: Errors.LOGIN_PASSWORD });
    }

    return {
      token: sign({ userId: user.id }, process.env.APP_SECRET),
      user
    };
  }
};

then on the client-side:

// using apollo-client
const LOGIN_MUTATION = gql`
  mutation Login($email: String!, $password: String!) {
    login(email: $email, password: $password) {
      token
    }
  }
`;
// ... standard sorta login component
  private onSubmit = async (variables: FormValues, { setErrors }: FormikProps<FormValues>) => {
    const { history, mutate } = this.props;
    try {
      const result = await mutate({
        variables
      });
      const { data: { login: { token } } } = result;
      login(token);
      history.replace('/');
    } catch (error) {
      console.log(error); // <-- right here it would be nice to be able to access custom AuthError values
    }
  };

I know there are a few ways for that error to show up and apollo-client ApolloError gives you an array of GraphqlError objects (which aren't Error objects, but formatted custom Objects). But somewhere nested in that ApolloError it'd be nice to be able to access AuthError.errorValues from the server, but it looks like those values are stripped before the error is sent in the response. Let me know if I am missing anything useful from the example, I was trying to keep it minimal.

@stephenlaughton can you setup a little launchpad with your example? So it's easier to test, try etc :wink: (not really have the time to setup an env today ^^)

I'm looking for the same functionality.

Specifically:

  • Ability to throw an Error in a resolver that results in a 401
  • Ability to throw field specific errors

Let me know if i can help!

Looking for the same functionality.

For instance only the message passed by the Error constructor is send to the client.

For example a server function would want to send :

  • ClientFriendlyMessage : to show in the client app
  • Debug message : more informations for the developer to know what's going on
  • Inner Exception message

How can I use ApolloError from graphql-yoga?

From above link I can easily create custom error like this -
new ApolloError(message, code, additionalProperties);

But how can I get reference to ApolloError ?

Looks like graphql-yoga doesn't export anything related with apollo-graphql.
So we need to install apollo-graphql in package.json and import ApolloError from it.
It is right?

Installing the apollo-server-errors@rc package should be enough

https://unpkg.com/[email protected]/dist/exports.d.ts

export {
  ApolloError,
  toApolloError,
  SyntaxError,
  ValidationError,
  AuthenticationError,
  ForbiddenError,
  UserInputError,
  gql
} from 'apollo-server-core'

Hello,

It would be convenient to expose these errors from graphql-yoga, as soon as you need internationalization or your app is in another language they're required.

I read this article about Error Handling using apollo-errors from Andre Konig, Hopefully, that helps you. Thx

Due to inactivity of this issue we have marked it stale. It will be closed if no further activity occurs.

Hey :wave:, It seems like this issue has been inactive for some time. In need for maintaining clear overview of the issues concerning the latest version of graphql-yoga we'll close it.
Feel free to reopen it at any time if you believe we should futher discuss its content. :slightly_smiling_face:

Any News about custom error in graphql-yoga?

Boink

Is there a specific reason not to import apollo-errors in graphql-yoga? or is there alternatives to not use apollo-errors?

Even though graphql-yoga doesnt expose error class we can manually install apollo-server-core and import error instance from it and use it like this

Install apollo-server-core

yarn add apollo-server-core

import it

const {AuthenticationError} = require("apollo-server-core");

throw error

if(!user) {
  throw new AuthenticationError("user not authenticated")
}

if anyone wants to read more

Was this page helpful?
0 / 5 - 0 ratings

Related issues

playerx picture playerx  路  5Comments

frederikhors picture frederikhors  路  4Comments

AhmadEl-Banna picture AhmadEl-Banna  路  5Comments

ahmedosama5200 picture ahmedosama5200  路  4Comments

anthonymetzler picture anthonymetzler  路  4Comments