apollo-server-core: use UserInputError for variable coercion errors#5091
Conversation
This particular error can be trivially triggered by clients, so it doesn't make sense to use `INTERNAL_SERVER_ERROR` for it. It seems like a good fit for `BAD_USER_INPUT`, which previously was only used if you explicitly throw a `UserInputError` in your app. Fixes #3498.
| const copy: ApolloError = | ||
| options && options.errorClass | ||
| options && options.errorConstructor | ||
| ? options.errorConstructor(error.message) |
There was a problem hiding this comment.
I did this because it turns out that UserInputError is not typeof ApolloError. The ApolloError constructor is (message: string, code?: string, extensions?: Record<string, any>) whereas the UserInputError constructor is (message: string, properties?: Record<string, any>) so there are valid calls to new ApolloError("x", "y") that can't be invoked on new UserInputError. (Other subclasses in this file just have (message: string) and I guess that's OK because additional arguments are just ignored?)
Now, fromGraphQLError only ever passes the first argument so both of those should be fine. But it doesn't work with typeof ApolloError. I did ask on internal Slack to see if anyone has any ideas.
There was a problem hiding this comment.
Ah OK I think I figured it out.
| const resultErrors = result.errors?.map((e) => { | ||
| if ( | ||
| e.nodes?.length === 1 && | ||
| e.nodes[0].kind === 'VariableDefinition' && |
There was a problem hiding this comment.
We should use graphql-js's Kind.VARIABLE_DEFINITION for this
There was a problem hiding this comment.
Sure, although TS actually does require the string constant here to be one of the possible valid strings (ie, typos won't compile).
| export interface ErrorOptions { | ||
| code?: string; | ||
| errorClass?: typeof ApolloError; | ||
| errorClass?: new (message: string) => ApolloError; |
There was a problem hiding this comment.
This seems fine, maybe a comment here that explains, though I also think it's pretty self-explanatory if you look at it for a second.
FWIW, I tried to improve the type here a bit with no luck - I tried to make this "condition" into an interface that UserInputError could implement but TS wasn't having it.
There was a problem hiding this comment.
Added a comment. FWIW I find this type to be easier to understand than typeof ApolloError anyway. I think the lesson for the future is to just take functions rather than class names/constructors though... easy enough to pass (s) => new MyClass(s)...
|
Oh ah, you approved — will merge now. |
| `Variable "$${e.nodes[0].variable.name.value}" got invalid value `, | ||
| ) | ||
| ) { | ||
| return fromGraphQLError(e, { |
There was a problem hiding this comment.
I don't know why codecov thinks this is uncovered. There's a test!
|
I've released a prerelease with this fix, version |
|
This is released in Apollo Server 2.23.0. |
This particular error can be trivially triggered by clients, so it doesn't make
sense to use
INTERNAL_SERVER_ERRORfor it. It seems like a good fit forBAD_USER_INPUT, which previously was only used if you explicitly throw aUserInputErrorin your app.Fixes #3498.