How to return an array of errors with graphQL

Viewed 5781

How can I return multiple error messages like this ?

"errors": [
  {
    "message": "first error",
    "locations": [
      {
        "line": 2,
        "column": 3
      }
    ],
    "path": [
      "somePath"
    ]
  },
  {
    "message": "second error",
    "locations": [
      {
        "line": 8,
        "column": 9
      }
    ],
    "path": [
      "somePath"
    ]
  },
]

On my server, if I do throw('an error'), it returns.

"errors": [
  {
    "message": "an error",
    "locations": [
      {
      }
    ],
    "path": ["somePath"]
  }
]

I would like to return an array of all the errors in the query. How can I add multiple errors to the errors array ?

5 Answers

Throw an error object with errors:[] in it. The errors array should have all the errors you wanted to throw together. Use the formatError function to format the error output. In the below example, I am using Apollo UserInputError. You can use GraphQLError as well. It doesn't matter.

const error = new UserInputError()
error.errors = errorslist.map((i) => {
  const _error = new UserInputError()
  _error.path = i.path
  _error.message = i.type
  return _error
})
throw error

new ApolloServer({
  typeDefs,
  resolvers,
  formatError: ({ message, path }) => ({
    message,
    path,
  }),
})

//sample output response
{
  "data": {
    "createUser": null
  },
  "errors": [
    {
      "message": "format",
      "path": "username"
    },
    {
      "message": "min",
      "path": "phone"
    }
  ]
}

Using ApolloServer I've found multiple errors will be returned when querying an array of items and an optional field's resolver errors.

// Schema
gql`
  type Foo {
    id: ID!
    bar: String # Optional
  }

  type Query {
    foos: [Foo!]!
  }
`;

// Resolvers
const resolvers = {
  Query: {
    foos: () => [{ id: 1 }, { id: 2 }]
  }
  Foo: {
    bar: (foo) => {
       throw new Error(`Failed to get Foo.bar: ${foo.id}`);
    }
  }
}

// Query
gql`
  query Foos {
    foos {
      id
      bar
    }
  }
`;

// Response
{
  "data": {
    "foos": [{ id: 1, bar: null }, { id: 2, bar: null }]
  },
  "errors": [{
    "message": "Failed to get Foo.bar: 1"
  }, {
    "message": "Failed to get Foo.bar: 2"
  }]
}

If Foo.bar is not optional, it will return just the first error.

If you want to return many errors, at once, I would recommend MultiError from VError which allows you to represent many errors in one error instance.

You can use the GraphQL Error Function, I have a example with TypeScript:

function throwError(message: string, path: any) {
    throw new GraphQLError(
        message,
        [],
        {body: '', name: ''},
        undefined,
        [path]
    )
}

And then I just call the function as many times as needed.

The JavaScript constructor looks like:

constructor(
    message: string,
    nodes?: $ReadOnlyArray<ASTNode> | ASTNode | void,
    source?: ?Source,
    positions?: ?$ReadOnlyArray<number>,
    path?: ?$ReadOnlyArray<string | number>,
    originalError?: ?Error,
    extensions?: ?{ [key: string]: mixed },
): void;

Check the graphql-js gitHub:

https://github.com/graphql/graphql-js/blob/master/src/error/GraphQLError.js#L22

Related