Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning multiple errors #205

Open
freiksenet opened this issue Oct 13, 2015 · 13 comments
Open

Returning multiple errors #205

freiksenet opened this issue Oct 13, 2015 · 13 comments

Comments

@freiksenet
Copy link
Contributor

Recent patch added ability to return Error from resolve to indicate failure. In a scenarios where validation happens in the resolve, it would be useful to be able to return multiple errors from one resolve.

I am not sure what would be the best way to do it, but otherwise I am willing to implement it. One way I see is to always check if result is a array and then check if elements of that list are all Errors.

@leebyron
Copy link
Contributor

Interesting. I'm curious what the use case is. I'm concerned about the burden this would put on the execution logic, but would entertain a PR here.

@jonsharratt
Copy link

👍

We potentially have a mutation where we would return an array of promises in the resolve function in turn they call different services and endpoints of those services and we would want them all to at least try and resolve all of them and get their results (success or errornus).

At the moment we we map through our Promise array, catch and setup the error rather to be returned rather than thrown so we can eventually filter out and throw the array from the mutations resolve.

Is there way from a mutation resolve function to push the array of errors to the context in order for them to list?

From GraphQL Schema 7.2.2:
If the data entry in the response is not null, the errors entry in the response may contain any errors that occurred during execution. If errors occurred during execution, it should contain those errors.

@freiksenet
Copy link
Contributor Author

Sorry for the lack of activity here.

@leebyron one use case is custom validation, for example in mutations. In Reindex we have migrate mutation, that accepts a new schema that database should move to. We try to detect all the problems that schema has at once, so that user doesn't need to call the endpoint repeatedly to find all the errors. Currently we have to solve this by concatenating errors together and then throwing them as one error in resolve function. Another example we have in Reindex is permissions, there can be multiple permissions missing during one resolve, esp when mutations involve modifying connected types.

I think a simple solution could be to create a new error type - 'GraphQLMultipleError', which accepts list of errors, and then just manage that at top level of the graphql resolve function, converting it to multiple errors there. This way we won't make the logic overly convoluted, but still allow outputting multiple errors to the user.

@leebyron
Copy link
Contributor

leebyron commented Apr 7, 2016

Interesting - for custom validation, would it be possible to use the validator phase for this, which supports multiple errors per step? Do you need to execute the query to understand the issues, or can issues be determined statically?

@amir-s
Copy link

amir-s commented Jan 10, 2017

@leebyron I ran into it and searched for it and I came here.

Basically I need to validate an input type based on some rules defined in the database, so the validation is at runtime.

I wrote the validation function which is kind of tied to all the resolver functions. It validates the input and if all the rules are passed, it runs the resolver function. It would be nice to have a way of throwing multiple errors if multiple fields fail on the validation (or perhaps a field doesn't pass multiple rules).

What I actually have done is I wrote a chain function which chains an array of functions together and return a single function which would be the resolve function. So basically chain accepts middlewares, the returned function, waits for each function in the array to be resolved (if it returns a promise), then calls the next one. The validator is kind of a middleware in this case.

resolve: chain(validator.validateBy('signup'), (_, {user}) => createUser(user))

@jakubknejzlik
Copy link

Just to share my trial, I've ended up using custom error approach in combination with joi package.

In mutation resolver I handle validation and throw the error if any:

//abortEarly is essential to get array of errors
const result = Joi.validate(data, schema, {abortEarly: false}); 
if (result.error) throw result.error

In error handler you can check if the error isJoi or just return details of originalError:

app.use('/graphql',graphqlExpress({
    schema: schema,
    formatError: (error) => {
      return {
        message: error.message,
        locations: error.locations,
        path: error.path,
        details: error.originalError.details
      }
    }
}))

On client you get one error (validation error), but you can access the details and display it in UI.

@julienvincent
Copy link

@jakubknejzlik Thanks for that. I have adopted the formatError + details approach myself. So far it's the most elegant solution I have come across. Ideally in future there is some sort of api for returning multiple errors as @freiksenet mentioned.

@francoisromain
Copy link

@julienvincent Could you explain how you do that, please? (i asked a related question here )

@julienvincent
Copy link

@francoisromain according to the referenced PR, looks like you can return an array of ResolverError now

@francoisromain
Copy link

@julienvincent the referenced PR is in graphql-ruby
does it work the same in express-graphql?

@IvanGoncharov IvanGoncharov added this to the v15.0.0 milestone Jan 29, 2019
@dyst5422
Copy link

@leebyron Use case

A resolver hits a number of back end services that may each complete successfully, or error out. In my resolver, I use Promise.allSettled and accumulate an array of errors at the end. I would like to use the built in error handling characteristics of client side solutions such as Apollo to be able to act on those errors. I have no way of generating multiple errors per resolver (or rather post processing the errors with formatError to add multiple errors to the errors array).

I think in my case, it might be a little outside the scope as I want to have partial results and errors from a single endpoint, but some imperative way to add errors would be a useful way to handle this case and others.

@IvanGoncharov IvanGoncharov removed this from the v15.x.x milestone Aug 13, 2020
@jaa134
Copy link

jaa134 commented Mar 15, 2021

Hello! Has there been any progress with this issue? I'm running into the same problem, but it seems like interest here has slowed down.

@yaacovCR
Copy link
Contributor

Related #3192

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests