-
Notifications
You must be signed in to change notification settings - Fork 2k
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
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.
errorClass?: typeof ApolloError; | ||
} | ||
|
||
export function fromGraphQLError(error: GraphQLError, options?: ErrorOptions) { | ||
const copy: ApolloError = | ||
options && options.errorClass | ||
options && options.errorConstructor | ||
? options.errorConstructor(error.message) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use graphql-js
's Kind.VARIABLE_DEFINITION
for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, although TS actually does require the string constant here to be one of the possible valid strings (ie, typos won't compile).
@@ -134,7 +134,7 @@ export function toApolloError( | |||
|
|||
export interface ErrorOptions { | |||
code?: string; | |||
errorClass?: typeof ApolloError; | |||
errorClass?: new (message: string) => ApolloError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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_ERROR
for it. It seems like a good fit forBAD_USER_INPUT
, which previously was only used if you explicitly throw aUserInputError
in your app.Fixes #3498.