Skip to content

apollo-server-core: use UserInputError for variable coercion errors#5091

Merged
glasser merged 4 commits into
mainfrom
glasser/variable-coercion-errors
Apr 8, 2021
Merged

apollo-server-core: use UserInputError for variable coercion errors#5091
glasser merged 4 commits into
mainfrom
glasser/variable-coercion-errors

Conversation

@glasser

@glasser glasser commented Apr 7, 2021

Copy link
Copy Markdown
Member

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.

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.
@glasser glasser requested a review from trevor-scheer April 7, 2021 00:01
const copy: ApolloError =
options && options.errorClass
options && options.errorConstructor
? options.errorConstructor(error.message)

Copy link
Copy Markdown
Member Author

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.

Copy link
Copy Markdown
Member Author

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' &&

Copy link
Copy Markdown
Contributor

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

Copy link
Copy Markdown
Member Author

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).

export interface ErrorOptions {
code?: string;
errorClass?: typeof ApolloError;
errorClass?: new (message: string) => ApolloError;

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Member Author

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)...

@glasser

glasser commented Apr 8, 2021

Copy link
Copy Markdown
Member Author

Oh ah, you approved — will merge now.

`Variable "$${e.nodes[0].variable.name.value}" got invalid value `,
)
) {
return fromGraphQLError(e, {

Copy link
Copy Markdown
Member Author

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!

@glasser glasser merged commit e3be328 into main Apr 8, 2021
@glasser glasser deleted the glasser/variable-coercion-errors branch April 8, 2021 19:13
@glasser

glasser commented Apr 9, 2021

Copy link
Copy Markdown
Member Author

I've released a prerelease with this fix, version 2.23.0-alpha.0. Try out the alpha and see if it works for you! Please provide any feedback in #5094.

@glasser

glasser commented Apr 14, 2021

Copy link
Copy Markdown
Member Author

This is released in Apollo Server 2.23.0.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong error code thrown for GraphQL validation failures in arguments using query variables

2 participants